home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / mpeg_play-2.1 / video.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  122KB  |  4,274 lines

  1. /* 
  2.  * video.c --
  3.  *
  4.  *      This file contains C code that implements the video decoder model.
  5.  *
  6.  */
  7.  
  8. /*
  9.  * Copyright (c) 1995 The Regents of the University of California.
  10.  * All rights reserved.  
  11.  *
  12.  * Permission to use, copy, modify, and distribute this software and its
  13.  * documentation for any purpose, without fee, and without written agreement is
  14.  * hereby granted, provided that the above copyright notice and the following
  15.  * two paragraphs appear in all copies of this software.
  16.  *
  17.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  18.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  19.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  20.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  21.  *
  22.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  23.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  24.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  25.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  26.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <assert.h>
  32.  
  33. #ifndef MIPS
  34. #include <sys/time.h>
  35. #else
  36. #include <sys/types.h>
  37. #include <sys/system.h>
  38. #endif
  39.  
  40. #include "decoders.h"
  41. #include "video.h"
  42. #include "util.h"
  43. #include "proto.h"
  44.  
  45. /* Declarations of functions. */
  46. static void ReconIMBlock();
  47. static void ReconPMBlock();
  48. static void ReconBMBlock();
  49. static void ReconBiMBlock();
  50. static void ReconSkippedBlock();
  51. static void DoPictureDisplay();
  52. static int ParseSeqHead();
  53. static int ParseGOP();
  54. static int ParsePicture();
  55. static int ParseSlice();
  56. static int ParseMacroBlock();
  57. static void ProcessSkippedPFrameMBlocks();
  58. static void ProcessSkippedBFrameMBlocks();
  59.  
  60. extern int ditherType;
  61. extern int matched_depth;
  62. char *ditherFlags;
  63. extern int seekValue;
  64.  
  65. /* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
  66.  
  67. #define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
  68.  
  69. /* Declare global pointer to vid stream used for current decoding. */
  70.  
  71. VidStream *curVidStream = NULL;
  72.  
  73. /* Set up array for fast conversion from zig zag order to row/column
  74.    coordinates.
  75. */
  76.  
  77. int zigzag[64][2] = {
  78.   0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1, 1, 2, 0, 3, 0, 4, 1, 3,
  79.   2, 2, 3, 1, 4, 0, 5, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4,
  80.   3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3, 3, 4, 2, 5, 1, 6, 0, 7,
  81.   1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6,
  82.   2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 5, 7, 6, 6,
  83.   7, 5, 7, 6, 6, 7, 7, 7};
  84. /* Array mapping zigzag to array pointer offset. */
  85.  
  86. int zigzag_direct[64] = {
  87.   0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
  88.   19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  89.   42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  90. 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
  91. /* Set up array for fast conversion from row/column coordinates to
  92.    zig zag order.
  93. */
  94.  
  95. int scan[8][8] = {
  96.   {0, 1, 5, 6, 14, 15, 27, 28},
  97.   {2, 4, 7, 13, 16, 26, 29, 42},
  98.   {3, 8, 12, 17, 25, 30, 41, 43},
  99.   {9, 11, 18, 24, 31, 40, 44, 53},
  100.   {10, 19, 23, 32, 39, 45, 52, 54},
  101.   {20, 22, 33, 38, 46, 51, 55, 60},
  102.   {21, 34, 37, 47, 50, 56, 59, 61},
  103. {35, 36, 48, 49, 57, 58, 62, 63}};
  104. /* Initialize P and B skip flags. */
  105.  
  106. static int No_P_Flag = FALSE;
  107. static int No_B_Flag = FALSE;
  108.  
  109. /* Max lum, chrom indices for illegal block checking. */
  110.  
  111. static int lmaxx;
  112. static int lmaxy;
  113. static int cmaxx;
  114. static int cmaxy;
  115.  
  116. /*
  117.  * We use a lookup table to make sure values stay in the 0..255 range.
  118.  * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this
  119.  * table the "crop table".
  120.  * MAX_NEG_CROP is the maximum neg/pos value we can handle.
  121.  */
  122.  
  123. #define MAX_NEG_CROP 2048
  124. #define NUM_CROP_ENTRIES (2048+2*MAX_NEG_CROP)
  125. static unsigned char cropTbl[NUM_CROP_ENTRIES];
  126.  
  127. /*
  128.   The following accounts for time and size  spent in various parsing acitivites
  129.   if ANALYSIS has been defined.
  130. */
  131.  
  132. #ifdef ANALYSIS
  133.  
  134.  
  135. unsigned int bitCount = 0;
  136.  
  137. int showmb_flag = 0;
  138. int showEachFlag = 0;
  139.  
  140. typedef struct {
  141.   int frametype;
  142.   unsigned int totsize;
  143.   unsigned int number;
  144.   unsigned int i_mbsize;
  145.   unsigned int p_mbsize;
  146.   unsigned int b_mbsize;
  147.   unsigned int bi_mbsize;
  148.   unsigned int i_mbnum;
  149.   unsigned int p_mbnum;
  150.   unsigned int b_mbnum;
  151.   unsigned int bi_mbnum;
  152.   unsigned int i_mbcbp[64];
  153.   unsigned int p_mbcbp[64];
  154.   unsigned int b_mbcbp[64];
  155.   unsigned int bi_mbcbp[64];
  156.   unsigned int i_mbcoeff[64];
  157.   unsigned int p_mbcoeff[64];
  158.   unsigned int b_mbcoeff[64];
  159.   unsigned int bi_mbcoeff[64];
  160.   double tottime;
  161. } Statval;
  162.  
  163. Statval stat_a[4];
  164. unsigned int pictureSizeCount;
  165. unsigned int mbSizeCount;
  166. unsigned int *mbCBPPtr, *mbCoeffPtr, *mbSizePtr;
  167. unsigned int cacheHit[8][8];
  168. unsigned int cacheMiss[8][8];
  169.  
  170. static void
  171. init_stat_struct(astat)
  172.   Statval *astat;
  173. {
  174.   int j;
  175.  
  176.   astat->frametype = 0;
  177.   astat->totsize = 0;
  178.   astat->number = 0;
  179.   astat->i_mbsize = 0;
  180.   astat->p_mbsize = 0;
  181.   astat->b_mbsize = 0;
  182.   astat->bi_mbsize = 0;
  183.   astat->i_mbnum = 0;
  184.   astat->p_mbnum = 0;
  185.   astat->b_mbnum = 0;
  186.   astat->bi_mbnum = 0;
  187.  
  188.   for (j = 0; j < 64; j++) {
  189.  
  190.     astat->i_mbcbp[j] = 0;
  191.     astat->p_mbcbp[j] = 0;
  192.     astat->b_mbcbp[j] = 0;
  193.     astat->bi_mbcbp[j] = 0;
  194.     astat->i_mbcoeff[j] = 0;
  195.     astat->p_mbcoeff[j] = 0;
  196.     astat->b_mbcoeff[j] = 0;
  197.     astat->bi_mbcoeff[j] = 0;
  198.   }
  199.   astat->tottime = 0.0;
  200. }
  201.  
  202. void
  203. init_stats()
  204. {
  205.   int i, j;
  206.  
  207.   for (i = 0; i < 4; i++) {
  208.     init_stat_struct(&(stat_a[i]));
  209.     stat_a[i].frametype = i;
  210.   }
  211.  
  212.   for (i = 0; i < 8; i++) {
  213.     for (j = 0; j < 8; j++) {
  214.       cacheHit[i][j] = 0;
  215.       cacheMiss[i][j] = 0;
  216.     }
  217.   }
  218.  
  219.   bitCount = 0;
  220. }
  221.  
  222. static void
  223. PrintOneStat()
  224. {
  225.   int i;
  226.  
  227.   printf("\n");
  228.   switch (stat_a[0].frametype) {
  229.   case I_TYPE:
  230.     printf("I FRAME\n");
  231.     break;
  232.   case P_TYPE:
  233.     printf("P FRAME\n");
  234.     break;
  235.   case B_TYPE:
  236.     printf("B FRAME\n");
  237.     break;
  238.   }
  239.  
  240.   printf("Size: %d bytes + %d bits\n", stat_a[0].totsize / 8, stat_a[0].totsize % 8);
  241.   if (stat_a[0].i_mbnum > 0) {
  242.     printf("\tI Macro Block Stats:\n");
  243.     printf("\t%d I Macroblocks\n", stat_a[0].i_mbnum);
  244.     printf("\tAvg. Size: %d bytes + %d bits\n",
  245.        stat_a[0].i_mbsize / (8 * stat_a[0].i_mbnum),
  246.        (stat_a[0].i_mbsize * stat_a[0].i_mbnum) % 8);
  247.     printf("\t\tCoded Block Pattern Histogram:\n");
  248.     for (i = 0; i < 64; i += 8) {
  249.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcbp[i],
  250.          stat_a[0].i_mbcbp[i + 1], stat_a[0].i_mbcbp[i + 2], stat_a[0].i_mbcbp[i + 3],
  251.          stat_a[0].i_mbcbp[i + 4], stat_a[0].i_mbcbp[i + 5], stat_a[0].i_mbcbp[i + 6],
  252.          stat_a[0].i_mbcbp[i + 7]);
  253.     }
  254.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  255.     for (i = 0; i < 64; i += 8) {
  256.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcoeff[i],
  257.          stat_a[0].i_mbcoeff[i + 1], stat_a[0].i_mbcoeff[i + 2],
  258.          stat_a[0].i_mbcoeff[i + 3], stat_a[0].i_mbcoeff[i + 4],
  259.          stat_a[0].i_mbcoeff[i + 5], stat_a[0].i_mbcoeff[i + 6],
  260.          stat_a[0].i_mbcoeff[i + 7]);
  261.     }
  262.   }
  263.   if (stat_a[0].p_mbnum > 0) {
  264.     printf("\tP Macro Block Stats:\n");
  265.     printf("\t%d P Macroblocks\n", stat_a[0].p_mbnum);
  266.     printf("\tAvg. Size: %d bytes + %d bits\n",
  267.        stat_a[0].p_mbsize / (8 * stat_a[0].p_mbnum),
  268.        (stat_a[0].p_mbsize / stat_a[0].p_mbnum) % 8);
  269.     printf("\t\tCoded Block Pattern Histogram:\n");
  270.     for (i = 0; i < 64; i += 8) {
  271.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcbp[i],
  272.          stat_a[0].p_mbcbp[i + 1], stat_a[0].p_mbcbp[i + 2], stat_a[0].p_mbcbp[i + 3],
  273.          stat_a[0].p_mbcbp[i + 4], stat_a[0].p_mbcbp[i + 5], stat_a[0].p_mbcbp[i + 6],
  274.          stat_a[0].p_mbcbp[i + 7]);
  275.     }
  276.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  277.     for (i = 0; i < 64; i += 8) {
  278.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcoeff[i],
  279.          stat_a[0].p_mbcoeff[i + 1], stat_a[0].p_mbcoeff[i + 2],
  280.          stat_a[0].p_mbcoeff[i + 3], stat_a[0].p_mbcoeff[i + 4],
  281.          stat_a[0].p_mbcoeff[i + 5], stat_a[0].p_mbcoeff[i + 6],
  282.          stat_a[0].p_mbcoeff[i + 7]);
  283.     }
  284.   }
  285.   if (stat_a[0].b_mbnum > 0) {
  286.     printf("\tB Macro Block Stats:\n");
  287.     printf("\t%d B Macroblocks\n", stat_a[0].b_mbnum);
  288.     printf("\tAvg. Size: %d bytes + %d bits\n",
  289.        stat_a[0].b_mbsize / (8 * stat_a[0].b_mbnum),
  290.        (stat_a[0].b_mbsize / stat_a[0].b_mbnum) % 8);
  291.     printf("\t\tCoded Block Pattern Histogram:\n");
  292.     for (i = 0; i < 64; i += 8) {
  293.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcbp[i],
  294.          stat_a[0].b_mbcbp[i + 1], stat_a[0].b_mbcbp[i + 2], stat_a[0].b_mbcbp[i + 3],
  295.          stat_a[0].b_mbcbp[i + 4], stat_a[0].b_mbcbp[i + 5], stat_a[0].b_mbcbp[i + 6],
  296.          stat_a[0].b_mbcbp[i + 7]);
  297.     }
  298.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  299.     for (i = 0; i < 64; i += 8) {
  300.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcoeff[i],
  301.          stat_a[0].b_mbcoeff[i + 1], stat_a[0].b_mbcoeff[i + 2],
  302.          stat_a[0].b_mbcoeff[i + 3], stat_a[0].b_mbcoeff[i + 4],
  303.          stat_a[0].b_mbcoeff[i + 5], stat_a[0].b_mbcoeff[i + 6],
  304.          stat_a[0].b_mbcoeff[i + 7]);
  305.     }
  306.   }
  307.   if (stat_a[0].bi_mbnum > 0) {
  308.     printf("\tBi Macro Block Stats:\n");
  309.     printf("\t%d Bi Macroblocks\n", stat_a[0].bi_mbnum);
  310.     printf("\tAvg. Size: %d bytes + %d bits\n",
  311.        stat_a[0].bi_mbsize / (8 * stat_a[0].bi_mbnum),
  312.        (stat_a[0].bi_mbsize * stat_a[0].bi_mbnum) % 8);
  313.     printf("\t\tCoded Block Pattern Histogram:\n");
  314.     for (i = 0; i < 64; i += 8) {
  315.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcbp[i],
  316.          stat_a[0].bi_mbcbp[i + 1], stat_a[0].bi_mbcbp[i + 2], stat_a[0].bi_mbcbp[i + 3],
  317.          stat_a[0].bi_mbcbp[i + 4], stat_a[0].bi_mbcbp[i + 5], stat_a[0].bi_mbcbp[i + 6],
  318.          stat_a[0].bi_mbcbp[i + 7]);
  319.     }
  320.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  321.     for (i = 0; i < 64; i += 8) {
  322.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcoeff[i],
  323.          stat_a[0].bi_mbcoeff[i + 1], stat_a[0].bi_mbcoeff[i + 2],
  324.          stat_a[0].bi_mbcoeff[i + 3], stat_a[0].bi_mbcoeff[i + 4],
  325.          stat_a[0].bi_mbcoeff[i + 5], stat_a[0].bi_mbcoeff[i + 6],
  326.          stat_a[0].bi_mbcoeff[i + 7]);
  327.     }
  328.   }
  329.   printf("\nTime to Decode: %g secs.\n", stat_a[0].tottime);
  330.   printf("****************\n");
  331. }
  332.  
  333. void
  334. PrintAllStats()
  335. {
  336.   int i, j;
  337.   unsigned int supertot, supernum;
  338.   double supertime;
  339.  
  340.   printf("\n");
  341.   printf("General Info: \n");
  342.   printf("Width: %d\nHeight: %d\n", curVidStream->mb_width * 16, curVidStream->mb_height * 16);
  343.  
  344.   for (i = 1; i < 4; i++) {
  345.  
  346.     if (stat_a[i].number == 0)
  347.       continue;
  348.  
  349.     switch (i) {
  350.     case 1:
  351.       printf("I FRAMES\n");
  352.       break;
  353.     case 2:
  354.       printf("P FRAMES\n");
  355.       break;
  356.     case 3:
  357.       printf("B FRAMES\n");
  358.       break;
  359.     }
  360.  
  361.     printf("Number: %d\n", stat_a[i].number);
  362.     printf("Avg. Size: %d bytes + %d bits\n",
  363.        stat_a[i].totsize / (8 * stat_a[i].number), (stat_a[i].totsize / stat_a[i].number) % 8);
  364.     if (stat_a[i].i_mbnum > 0) {
  365.       printf("\tI Macro Block Stats:\n");
  366.       printf("\t%d I Macroblocks\n", stat_a[i].i_mbnum);
  367.       printf("\tAvg. Size: %d bytes + %d bits\n",
  368.          stat_a[i].i_mbsize / (8 * stat_a[i].i_mbnum),
  369.          (stat_a[i].i_mbsize / stat_a[i].i_mbnum) % 8);
  370.       printf("\t\tCoded Block Pattern Histogram:\n");
  371.       for (j = 0; j < 64; j += 8) {
  372.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcbp[j],
  373.            stat_a[i].i_mbcbp[j + 1], stat_a[i].i_mbcbp[j + 2], stat_a[i].i_mbcbp[j + 3],
  374.            stat_a[i].i_mbcbp[j + 4], stat_a[i].i_mbcbp[j + 5], stat_a[i].i_mbcbp[j + 6],
  375.            stat_a[i].i_mbcbp[j + 7]);
  376.       }
  377.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  378.       for (j = 0; j < 64; j += 8) {
  379.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcoeff[j],
  380.            stat_a[i].i_mbcoeff[j + 1], stat_a[i].i_mbcoeff[j + 2],
  381.            stat_a[i].i_mbcoeff[j + 3], stat_a[i].i_mbcoeff[j + 4],
  382.            stat_a[i].i_mbcoeff[j + 5], stat_a[i].i_mbcoeff[j + 6],
  383.            stat_a[i].i_mbcoeff[j + 7]);
  384.       }
  385.     }
  386.     if (stat_a[i].p_mbnum > 0) {
  387.       printf("\tP Macro Block Stats:\n");
  388.       printf("\t%d P Macroblocks\n", stat_a[i].p_mbnum);
  389.       printf("\tAvg. Size: %d bytes + %d bits\n",
  390.          stat_a[i].p_mbsize / (8 * stat_a[i].p_mbnum),
  391.          (stat_a[i].p_mbsize / stat_a[i].p_mbnum) % 8);
  392.       printf("\t\tCoded Block Pattern Histogram:\n");
  393.       for (j = 0; j < 64; j += 8) {
  394.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcbp[j],
  395.            stat_a[i].p_mbcbp[j + 1], stat_a[i].p_mbcbp[j + 2], stat_a[i].p_mbcbp[j + 3],
  396.            stat_a[i].p_mbcbp[j + 4], stat_a[i].p_mbcbp[j + 5], stat_a[i].p_mbcbp[j + 6],
  397.            stat_a[i].p_mbcbp[j + 7]);
  398.       }
  399.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  400.       for (j = 0; j < 64; j += 8) {
  401.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcoeff[j],
  402.            stat_a[i].p_mbcoeff[j + 1], stat_a[i].p_mbcoeff[j + 2],
  403.            stat_a[i].p_mbcoeff[j + 3], stat_a[i].p_mbcoeff[j + 4],
  404.            stat_a[i].p_mbcoeff[j + 5], stat_a[i].p_mbcoeff[j + 6],
  405.            stat_a[i].p_mbcoeff[j + 7]);
  406.       }
  407.     }
  408.     if (stat_a[i].b_mbnum > 0) {
  409.       printf("\tB Macro Block Stats:\n");
  410.       printf("\t%d B Macroblocks\n", stat_a[i].b_mbnum);
  411.       printf("\tAvg. Size: %d bytes + %d bits\n",
  412.          stat_a[i].b_mbsize / (8 * stat_a[i].b_mbnum),
  413.          (stat_a[i].b_mbsize * stat_a[i].b_mbnum) % 8);
  414.       printf("\t\tCoded Block Pattern Histogram:\n");
  415.       for (j = 0; j < 64; j += 8) {
  416.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcbp[j],
  417.            stat_a[i].b_mbcbp[j + 1], stat_a[i].b_mbcbp[j + 2], stat_a[i].b_mbcbp[j + 3],
  418.            stat_a[i].b_mbcbp[j + 4], stat_a[i].b_mbcbp[j + 5], stat_a[i].b_mbcbp[j + 6],
  419.            stat_a[i].b_mbcbp[j + 7]);
  420.       }
  421.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  422.       for (j = 0; j < 64; j += 8) {
  423.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcoeff[j],
  424.            stat_a[i].b_mbcoeff[j + 1], stat_a[i].b_mbcoeff[j + 2],
  425.            stat_a[i].b_mbcoeff[j + 3], stat_a[i].b_mbcoeff[j + 4],
  426.            stat_a[i].b_mbcoeff[j + 5], stat_a[i].b_mbcoeff[j + 6],
  427.            stat_a[i].b_mbcoeff[j + 7]);
  428.       }
  429.     }
  430.     if (stat_a[i].bi_mbnum > 0) {
  431.       printf("\tBi Macro Block Stats:\n");
  432.       printf("\t%d Bi Macroblocks\n", stat_a[i].bi_mbnum);
  433.       printf("\tAvg. Size: %d bytes + %d bits\n",
  434.          stat_a[i].bi_mbsize / (8 * stat_a[i].bi_mbnum),
  435.          (stat_a[i].bi_mbsize * stat_a[i].bi_mbnum) % 8);
  436.       printf("\t\tCoded Block Pattern Histogram:\n");
  437.       for (j = 0; j < 64; j += 8) {
  438.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcbp[j],
  439.            stat_a[i].bi_mbcbp[j + 1], stat_a[i].bi_mbcbp[j + 2], stat_a[i].bi_mbcbp[j + 3],
  440.            stat_a[i].bi_mbcbp[j + 4], stat_a[i].bi_mbcbp[j + 5], stat_a[i].bi_mbcbp[j + 6],
  441.            stat_a[i].bi_mbcbp[j + 7]);
  442.       }
  443.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  444.       for (j = 0; j < 64; j += 8) {
  445.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcoeff[j],
  446.            stat_a[i].bi_mbcoeff[j + 1], stat_a[i].bi_mbcoeff[j + 2],
  447.            stat_a[i].bi_mbcoeff[j + 3], stat_a[i].bi_mbcoeff[j + 4],
  448.            stat_a[i].bi_mbcoeff[j + 5], stat_a[i].bi_mbcoeff[j + 6],
  449.            stat_a[i].bi_mbcoeff[j + 7]);
  450.       }
  451.     }
  452.     printf("\nAvg. Time to Decode: %f secs.\n",
  453.        (stat_a[i].tottime / ((double) stat_a[i].number)));
  454.     printf("\n");
  455.     printf("*************************\n\n");
  456.   }
  457.  
  458.   supertot = stat_a[1].totsize + stat_a[2].totsize + stat_a[3].totsize;
  459.   supernum = stat_a[1].number + stat_a[2].number + stat_a[3].number;
  460.   supertime = stat_a[1].tottime + stat_a[2].tottime + stat_a[3].tottime;
  461.  
  462.   printf("Total Number of Frames: %d\n", supernum);
  463.   printf("Avg Frame Size: %d bytes %d bits\n",
  464.      supertot / (8 * supernum), (supertot / supernum) % 8);
  465.   printf("Total Time Decoding: %g secs.\n", supertime);
  466.   printf("Avg Decoding Time/Frame: %g secs.\n", supertime / ((double) supernum));
  467.   printf("Avg Decoding Frames/Sec: %g secs.\n", ((double) supernum) / supertime);
  468.   printf("\n");
  469.  
  470.   printf("Cache Hits/Miss\n");
  471.   for (i = 0; i < 8; i++) {
  472.     printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n",
  473.        cacheHit[i][0], cacheMiss[i][0], cacheHit[i][1], cacheMiss[i][1],
  474.        cacheHit[i][2], cacheMiss[i][2], cacheHit[i][3], cacheMiss[i][3]);
  475.     printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n",
  476.        cacheHit[i][4], cacheMiss[i][4], cacheHit[i][5], cacheMiss[i][5],
  477.        cacheHit[i][6], cacheMiss[i][6], cacheHit[i][7], cacheMiss[i][7]);
  478.   }
  479.  
  480. }
  481.  
  482. static void
  483. CollectStats()
  484. {
  485.   int i, j;
  486.  
  487.   i = stat_a[0].frametype;
  488.  
  489.   stat_a[i].totsize += stat_a[0].totsize;
  490.   stat_a[i].number += stat_a[0].number;
  491.   stat_a[i].i_mbsize += stat_a[0].i_mbsize;
  492.   stat_a[i].p_mbsize += stat_a[0].p_mbsize;
  493.   stat_a[i].b_mbsize += stat_a[0].b_mbsize;
  494.   stat_a[i].bi_mbsize += stat_a[0].bi_mbsize;
  495.   stat_a[i].i_mbnum += stat_a[0].i_mbnum;
  496.   stat_a[i].p_mbnum += stat_a[0].p_mbnum;
  497.   stat_a[i].b_mbnum += stat_a[0].b_mbnum;
  498.   stat_a[i].bi_mbnum += stat_a[0].bi_mbnum;
  499.  
  500.   for (j = 0; j < 64; j++) {
  501.  
  502.     stat_a[i].i_mbcbp[j] += stat_a[0].i_mbcbp[j];
  503.     stat_a[i].p_mbcbp[j] += stat_a[0].p_mbcbp[j];
  504.     stat_a[i].b_mbcbp[j] += stat_a[0].b_mbcbp[j];
  505.     stat_a[i].bi_mbcbp[j] += stat_a[0].bi_mbcbp[j];
  506.     stat_a[i].i_mbcoeff[j] += stat_a[0].i_mbcoeff[j];
  507.     stat_a[i].p_mbcoeff[j] += stat_a[0].p_mbcoeff[j];
  508.     stat_a[i].b_mbcoeff[j] += stat_a[0].b_mbcoeff[j];
  509.     stat_a[i].bi_mbcoeff[j] += stat_a[0].bi_mbcoeff[j];
  510.   }
  511.  
  512.   stat_a[i].tottime += stat_a[0].tottime;
  513.  
  514.   init_stat_struct(&(stat_a[0]));
  515. }
  516.  
  517. static unsigned int
  518. bitCountRead()
  519. {
  520.   return bitCount;
  521. }
  522.  
  523. static void
  524. StartTime()
  525. {
  526.   stat_a[0].tottime = ReadSysClock();
  527. }
  528.  
  529. static void
  530. EndTime()
  531. {
  532.   stat_a[0].tottime = ReadSysClock() - stat_a[0].tottime;
  533. }
  534. #endif
  535.  
  536. double realTimeStart;
  537. int totNumFrames = 0;
  538.  
  539.  
  540. /*
  541.  *--------------------------------------------------------------
  542.  *
  543.  * ReadSysClock --
  544.  *
  545.  *    Computes the current time according to the system clock.
  546.  *
  547.  * Results:
  548.  *  The current time according to the system clock.
  549.  *
  550.  * Side effects:
  551.  *      None.
  552.  *
  553.  *--------------------------------------------------------------
  554.  */
  555.  
  556. double
  557. ReadSysClock()
  558. {
  559.   struct timeval tv;
  560.   (void) gettimeofday(&tv, (struct timezone *)NULL);
  561.   return (tv.tv_sec + tv.tv_usec / 1000000.0);
  562. }
  563.  
  564.  
  565. /*
  566.  *--------------------------------------------------------------
  567.  *
  568.  * PrintTimeInfo --
  569.  *
  570.  *    Displays statistics regarding the video playback time.
  571.  *
  572.  * Results:
  573.  *  Outputs time statistics to the screen.
  574.  *
  575.  * Side effects:
  576.  *      None.
  577.  *
  578.  *--------------------------------------------------------------
  579.  */
  580.  
  581. void
  582. PrintTimeInfo()
  583. {
  584.   double spent;
  585.  
  586.   spent = ReadSysClock() - realTimeStart;
  587.  
  588.   if (!quietFlag) {
  589.     printf("\nReal Time Spent (After Initializations): %f secs.\n", spent);
  590.     printf("Avg. Frames/Sec: %f\n", ((double) totNumFrames) / spent);
  591.   }
  592. }
  593.  
  594.  
  595.  
  596.  
  597. /*
  598.  *--------------------------------------------------------------
  599.  *
  600.  * NewVidStream --
  601.  *
  602.  *    Allocates and initializes a VidStream structure. Takes
  603.  *      as parameter requested size for buffer length.
  604.  *
  605.  * Results:
  606.  *    A pointer to the new VidStream structure.
  607.  *
  608.  * Side effects:
  609.  *      None.
  610.  *
  611.  *--------------------------------------------------------------
  612.  */
  613.  
  614. VidStream *
  615. NewVidStream(buffer_len)
  616.   unsigned int buffer_len;
  617. {
  618.   int i, j;
  619.   VidStream *new;
  620.   static unsigned char default_intra_matrix[64] = {
  621.     8, 16, 19, 22, 26, 27, 29, 34,
  622.     16, 16, 22, 24, 27, 29, 34, 37,
  623.     19, 22, 26, 27, 29, 34, 34, 38,
  624.     22, 22, 26, 27, 29, 34, 37, 40,
  625.     22, 26, 27, 29, 32, 35, 40, 48,
  626.     26, 27, 29, 32, 35, 40, 48, 58,
  627.     26, 27, 29, 34, 38, 46, 56, 69,
  628.   27, 29, 35, 38, 46, 56, 69, 83};
  629.  
  630.   /* Check for legal buffer length. */
  631.  
  632.   if (buffer_len < 4)
  633.     return NULL;
  634.  
  635.   /* Make buffer length multiple of 4. */
  636.  
  637.   buffer_len = (buffer_len + 3) >> 2;
  638.  
  639.   /* Allocate memory for new structure. */
  640.  
  641.   new = (VidStream *) malloc(sizeof(VidStream));
  642.  
  643.   /* Initialize pointers to extension and user data. */
  644.  
  645.   new->group.ext_data = new->group.user_data =
  646.     new->picture.extra_info = new->picture.user_data =
  647.     new->picture.ext_data = new->slice.extra_info =
  648.     new->ext_data = new->user_data = NULL;
  649.  
  650.   /* Copy default intra matrix. */
  651.  
  652.   for (i = 0; i < 8; i++) {
  653.     for (j = 0; j < 8; j++) {
  654.       new->intra_quant_matrix[i][j] = default_intra_matrix[i * 8 + j];
  655.     }
  656.   }
  657.  
  658.   /* Initialize crop table. */
  659.  
  660.   for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) {
  661.     if (i <= 0) {
  662.       cropTbl[i + MAX_NEG_CROP] = 0;
  663. #ifdef TWELVE_BITS
  664.     } else if (i >= 2047) {
  665.       cropTbl[i + MAX_NEG_CROP] = 2047;
  666. #endif
  667.     } else if (i >= 255) {
  668.       cropTbl[i + MAX_NEG_CROP] = 255;
  669.     } else {
  670.       cropTbl[i + MAX_NEG_CROP] = i;
  671.     }
  672.   }
  673.  
  674.   /* Initialize non intra quantization matrix. */
  675.  
  676.   for (i = 0; i < 8; i++) {
  677.     for (j = 0; j < 8; j++) {
  678.       new->non_intra_quant_matrix[i][j] = 16;
  679.     }
  680.   }
  681.  
  682.   /* Initialize pointers to image spaces. */
  683.  
  684.   new->current = new->past = new->future = NULL;
  685.   for (i = 0; i < RING_BUF_SIZE; i++) {
  686.     new->ring[i] = NULL;
  687.   }
  688.  
  689.   /* Create buffer. */
  690.   
  691.   new->buf_start = (unsigned int *) malloc(buffer_len * 4);
  692.  
  693.   /*
  694.    * Set max_buf_length to one less than actual length to deal with messy
  695.    * data without proper seq. end codes.
  696.    */
  697.  
  698.   new->max_buf_length = buffer_len - 1;
  699.  
  700.   /* Initialize bitstream i/o fields. */
  701.  
  702.   new->bit_offset = 0;
  703.   new->buf_length = 0;
  704.   new->buffer = new->buf_start;
  705.  
  706.  
  707.   /* Return structure. */
  708.  
  709.   return new;
  710. }
  711.  
  712.  
  713.  
  714. /*
  715.  *--------------------------------------------------------------
  716.  *
  717.  * DestroyVidStream --
  718.  *
  719.  *    Deallocates a VidStream structure.
  720.  *
  721.  * Results:
  722.  *      None.
  723.  *
  724.  * Side effects:
  725.  *    None.
  726.  *
  727.  *--------------------------------------------------------------
  728.  */
  729. void
  730. DestroyVidStream(astream)
  731.   VidStream *astream;
  732. {
  733.   int i;
  734.  
  735.   if (astream->ext_data != NULL)
  736.     free(astream->ext_data);
  737.  
  738.   if (astream->user_data != NULL)
  739.     free(astream->user_data);
  740.  
  741.   if (astream->group.ext_data != NULL)
  742.     free(astream->group.ext_data);
  743.  
  744.   if (astream->group.user_data != NULL)
  745.     free(astream->group.user_data);
  746.  
  747.   if (astream->picture.extra_info != NULL)
  748.     free(astream->picture.extra_info);
  749.  
  750.   if (astream->picture.ext_data != NULL)
  751.     free(astream->picture.ext_data);
  752.  
  753.   if (astream->picture.user_data != NULL)
  754.     free(astream->picture.user_data);
  755.  
  756.   if (astream->slice.extra_info != NULL)
  757.     free(astream->slice.extra_info);
  758.  
  759.   if (astream->buf_start != NULL)
  760.     free(astream->buf_start);
  761.  
  762.   for (i = 0; i < RING_BUF_SIZE; i++) {
  763.     if (astream->ring[i] != NULL) {
  764.       DestroyPictImage(astream->ring[i]);
  765.       astream->ring[i] = NULL;
  766.     }
  767.   }
  768.  
  769.   free((char *) astream);
  770. }
  771.  
  772.  
  773.  
  774.  
  775. /*
  776.  *--------------------------------------------------------------
  777.  *
  778.  * NewPictImage --
  779.  *
  780.  *    Allocates and initializes a PictImage structure.
  781.  *      The width and height of the image space are passed in
  782.  *      as parameters.
  783.  *
  784.  * Results:
  785.  *    A pointer to the new PictImage structure.
  786.  *
  787.  * Side effects:
  788.  *    None.
  789.  *
  790.  *--------------------------------------------------------------
  791.  */
  792.  
  793. PictImage *
  794. NewPictImage(width, height)
  795.   unsigned int width, height;
  796. {
  797.   PictImage *new;
  798.  
  799.   /* Allocate memory space for new structure. */
  800.  
  801.   new = (PictImage *) malloc(sizeof(PictImage));
  802.  
  803.  
  804.   /* Allocate memory for image spaces. */
  805.  
  806. #ifdef SH_MEM
  807.   new->ximage = NULL;
  808.   
  809.   if (shmemFlag) {
  810.     Visual *fc_visual;
  811.     unsigned int depth;
  812.     /*
  813.      * factor is 1 or 2
  814.      */
  815.     int factor = 1 + IS_2x2_DITHER(ditherType);
  816.  
  817.     Visual *FindFullColorVisual();
  818.     
  819.     if (ditherType == FULL_COLOR_DITHER || ditherType == FULL_COLOR2_DITHER) {
  820.       fc_visual = FindFullColorVisual(display, &depth);
  821.       new->ximage = XShmCreateImage(display, fc_visual, depth, ZPixmap,
  822.                     NULL, &(new->shminfo), width * factor,
  823.                     height * factor);
  824.     } else if (ditherType == FULL_COLOR2_DITHER) {
  825.       fc_visual = FindFullColorVisual(display, &depth);
  826.       new->ximage = XShmCreateImage(display, fc_visual, depth, ZPixmap,
  827.                     NULL, &(new->shminfo), width*2, height*2);
  828.     } else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
  829.       new->ximage = XShmCreateImage(display, None, 1, XYBitmap,
  830.                     NULL, &(new->shminfo), width * factor,
  831.                     height * factor);
  832.     } else {
  833.       new->ximage = XShmCreateImage(display, None, matched_depth, ZPixmap, NULL,
  834.                     &(new->shminfo), width * factor,
  835.                     height * factor);
  836.     }
  837.  
  838.     /* If no go, then revert to normal Xlib calls. */
  839.     
  840.     if (new->ximage == NULL) {
  841.       shmemFlag = 0;
  842.       if (!quietFlag) {
  843.         fprintf(stderr, "Shared memory error, disabling.\n");
  844.         fprintf(stderr, "Ximage error.\n");
  845.       }
  846.       goto shmemerror;
  847.     }
  848.  
  849.     /* Success here, continue. */
  850.  
  851. #ifdef LITTLE_ENDIAN_ARCHITECTURE
  852.     new->ximage->byte_order = LSBFirst;
  853.     new->ximage->bitmap_bit_order = LSBFirst;
  854. #else
  855.     new->ximage->byte_order = MSBFirst;
  856.     new->ximage->bitmap_bit_order = MSBFirst;
  857. #endif
  858.     
  859.     new->shminfo.shmid = shmget(IPC_PRIVATE, (unsigned int) (new->ximage->bytes_per_line *
  860.                           new->ximage->height),
  861.                 IPC_CREAT | 0777);
  862.     
  863.     if (new->shminfo.shmid < 0) {
  864.       XDestroyImage(new->ximage);
  865.       new->ximage = NULL;
  866.       shmemFlag = 0;
  867.       if (!quietFlag) {
  868.         fprintf(stderr, "Shared memory error, disabling.\n");
  869.         fprintf(stderr, "Seg. id. error.\n");
  870.       }
  871.       goto shmemerror;
  872.     }
  873.  
  874.     new->shminfo.shmaddr = (char *) shmat(new->shminfo.shmid, 0, 0);
  875.  
  876.     if (new->shminfo.shmaddr == ((char *) -1)) {
  877.       XDestroyImage(new->ximage);
  878.       new->ximage = NULL;
  879.       shmemFlag = 0;
  880.       if (!quietFlag) {
  881.         fprintf(stderr, "Shared memory error, disabling.\n");
  882.         fprintf(stderr, "Address error.\n");
  883.       }
  884.       goto shmemerror;
  885.     }
  886.  
  887.     new->ximage->data = new->shminfo.shmaddr;
  888.     new->display = (unsigned char *) new->ximage->data;
  889.     new->shminfo.readOnly = False;
  890.  
  891.     XShmAttach(display, &(new->shminfo));
  892.     XSync(display, False);
  893.  
  894.     if (gXErrorFlag) {
  895.       /* Ultimate failure here. */
  896.       XShmDetach(display,&(new->shminfo));
  897.       XSync(display, False);
  898.       XDestroyImage(new->ximage);
  899.       shmdt (new->shminfo.shmaddr);
  900.       shmctl (new->shminfo.shmid, IPC_RMID, 0);
  901.       new->ximage = NULL;
  902.       shmemFlag = 0;
  903.       if (!quietFlag) {
  904.         fprintf(stderr, "Shared memory error, disabling.\n");
  905.       }
  906.       gXErrorFlag = 0;
  907.       goto shmemerror;
  908.     } else {
  909.       shmctl(new->shminfo.shmid, IPC_RMID, 0);
  910.     }
  911.     
  912.     if (!quietFlag) {
  913.       fprintf(stderr, "Sharing memory.\n");
  914.     }
  915.   } else
  916. #endif
  917.     {
  918.     int temp_sz;
  919.     int factor;
  920. shmemerror:
  921.     temp_sz = matched_depth >> 3;
  922.     if(!temp_sz) temp_sz = 1;
  923.     if(temp_sz == 3) temp_sz = 4;
  924.     factor = 1 + IS_2x2_DITHER(ditherType); /* 1 or 2 */
  925.  
  926.     new->display = (unsigned char *) malloc(width * height * temp_sz *
  927.                                                             factor * factor);
  928.     }
  929.   new->luminance = (unsigned char *) malloc(width * height);
  930.   new->Cr = (unsigned char *) malloc(width * height / 4);
  931.   new->Cb = (unsigned char *) malloc(width * height / 4);
  932.   
  933.   /* Reset locked flag. */
  934.   
  935.   new->locked = 0;
  936.  
  937.   /* Return pointer to new structure. */
  938.  
  939.   return new;
  940. }
  941.  
  942.  
  943.  
  944. /*
  945.  *--------------------------------------------------------------
  946.  *
  947.  * DestroyPictImage --
  948.  *
  949.  *    Deallocates a PictImage structure.
  950.  *
  951.  * Results:
  952.  *      None.
  953.  *
  954.  * Side effects:
  955.  *    None.
  956.  *
  957.  *--------------------------------------------------------------
  958.  */
  959. void
  960. DestroyPictImage(apictimage)
  961.   PictImage *apictimage;
  962. {
  963.   if (apictimage->luminance != NULL) {
  964.     free(apictimage->luminance);
  965.   }
  966.   if (apictimage->Cr != NULL) {
  967.     free(apictimage->Cr);
  968.   }
  969.   if (apictimage->Cb != NULL) {
  970.     free(apictimage->Cb);
  971.   }
  972. #ifdef SH_MEM
  973.   if ((apictimage->ximage != NULL)&&!noDisplayFlag&&shmemFlag) {
  974.     XShmDetach(display, &(apictimage->shminfo));
  975.     XDestroyImage(apictimage->ximage);
  976.     shmdt(apictimage->shminfo.shmaddr);
  977.     apictimage->ximage = NULL;
  978.     apictimage->display = NULL;
  979.   }
  980. #endif
  981.  
  982.   if (apictimage->display != NULL) {
  983.     free(apictimage->display);
  984.   }
  985.   free(apictimage);
  986. }
  987.  
  988.  
  989. /*
  990.  *--------------------------------------------------------------
  991.  *
  992.  * mpegVidRsrc --
  993.  *
  994.  *      Parses bit stream until MB_QUANTUM number of
  995.  *      macroblocks have been decoded or current slice or
  996.  *      picture ends, whichever comes first. If the start
  997.  *      of a frame is encountered, the frame is time stamped
  998.  *      with the value passed in time_stamp. If the value
  999.  *      passed in buffer is not null, the video stream buffer
  1000.  *      is set to buffer and the length of the buffer is
  1001.  *      expected in value passed in through length. The current
  1002.  *      video stream is set to vid_stream. If vid_stream
  1003.  *      is passed as NULL, a new VidStream structure is created
  1004.  *      and initialized and used as the current video stream.
  1005.  *
  1006.  * Results:
  1007.  *      A pointer to the video stream structure used.
  1008.  *
  1009.  * Side effects:
  1010.  *      Bit stream is irreversibly parsed. If a picture is completed,
  1011.  *      a function is called to display the frame at the correct time.
  1012.  *
  1013.  *--------------------------------------------------------------
  1014.  */
  1015.  
  1016. VidStream *
  1017. mpegVidRsrc(time_stamp, vid_stream)
  1018.   TimeStamp time_stamp;
  1019.   VidStream *vid_stream;
  1020. {
  1021.   static int first = 1;
  1022.   unsigned int data;
  1023.   int i, status;
  1024.  
  1025.   /* If vid_stream is null, create new VidStream structure. */
  1026.  
  1027.   if (vid_stream == NULL) {
  1028.     return NULL;
  1029.   }
  1030.   /*
  1031.    * Set global curVidStream to vid_stream. Necessary because bit i/o use
  1032.    * curVidStream and are not passed vid_stream. Also set global bitstream
  1033.    * parameters.
  1034.    */
  1035.  
  1036.   curVidStream = vid_stream;
  1037.   bitOffset = curVidStream->bit_offset;
  1038.   bufLength = curVidStream->buf_length;
  1039.   bitBuffer = curVidStream->buffer;
  1040.  
  1041.   /*
  1042.    * If called for the first time, find start code, make sure it is a
  1043.    * sequence start code.
  1044.    */
  1045.  
  1046.   if (first) {
  1047.     next_start_code();  /* sets curBits */
  1048.     show_bits32(data);
  1049.     if (data != SEQ_START_CODE) {
  1050.       fprintf(stderr, "This is not an MPEG video stream. (%x)\n",data);
  1051.       DestroyVidStream(curVidStream);
  1052.       exit(1);
  1053.     }
  1054.     first = 0;
  1055.   } else {
  1056. #ifdef UTIL2
  1057.     curBits = *curVidStream->buffer << bitOffset;
  1058. #else
  1059.     curBits = *curVidStream->buffer;
  1060. #endif
  1061.   }
  1062.  
  1063.   /* Get next 32 bits (size of start codes). */
  1064.  
  1065.   show_bits32(data);
  1066.  
  1067.   /*
  1068.    * Process according to start code (or parse macroblock if not a start code
  1069.    * at all).
  1070.    */
  1071.  
  1072.   switch (data) {
  1073.  
  1074.   case SEQ_END_CODE:
  1075.   case 0x000001b9:   /*  handle ISO_11172_END_CODE too */
  1076.  
  1077.     /* Display last frame. */
  1078.  
  1079.     if (vid_stream->future != NULL) {
  1080.       vid_stream->current = vid_stream->future;
  1081.       ExecuteDisplay(vid_stream);
  1082.     }
  1083.     
  1084.     /* Sequence done. Do the right thing. For right now, exit. */
  1085.  
  1086.     if (!quietFlag) {
  1087.       fprintf(stderr, "\nDone!\n");
  1088.     }
  1089.  
  1090. #ifdef ANALYSIS
  1091.     PrintAllStats();
  1092. #endif
  1093.     PrintTimeInfo();
  1094.  
  1095.     if (loopFlag) {
  1096.       clear_data_stream(&vid_stream->buf_start,
  1097.             &vid_stream->max_buf_length,
  1098.             &bufLength, &bitBuffer);
  1099.       longjmp(env, 1);
  1100.     }
  1101.  
  1102.     DestroyVidStream(curVidStream);
  1103.     exit(0);
  1104.     break;
  1105.  
  1106.   case SEQ_START_CODE:
  1107.  
  1108.     /* Sequence start code. Parse sequence header. */
  1109.  
  1110.     if (ParseSeqHead(vid_stream) != PARSE_OK)
  1111.       goto error;
  1112.  
  1113.     /*
  1114.      * Return after sequence start code so that application above can use
  1115.      * info in header.
  1116.      */
  1117.     if (seekValue > 0) {
  1118.       SeekStream(vid_stream);      
  1119.     }
  1120.  
  1121.  
  1122.     goto done;
  1123.  
  1124.   case GOP_START_CODE:
  1125.  
  1126.     /* Group of Pictures start code. Parse gop header. */
  1127.  
  1128.     if (ParseGOP(vid_stream) != PARSE_OK)
  1129.       goto error;
  1130.     goto done;
  1131.  
  1132.   case PICTURE_START_CODE:
  1133.  
  1134.     /* Picture start code. Parse picture header and first slice header. */
  1135.  
  1136.     status = ParsePicture(vid_stream, time_stamp);
  1137.  
  1138.     if (status == SKIP_PICTURE) {
  1139.       next_start_code();
  1140.       fprintf(stderr, "Skipping picture...");
  1141.       while (!next_bits(32, PICTURE_START_CODE)) {
  1142.     if (next_bits(32, GOP_START_CODE))
  1143.       break;
  1144.     else if (next_bits(32, SEQ_END_CODE))
  1145.       break;
  1146.     flush_bits(24);
  1147.     next_start_code();
  1148.       }
  1149.       fprintf(stderr, "Done.\n");
  1150.       goto done;
  1151.     } else if (status != PARSE_OK)
  1152.       goto error;
  1153.  
  1154.  
  1155.     if (ParseSlice(vid_stream) != PARSE_OK)
  1156.       goto error;
  1157.     break;
  1158.  
  1159.   default:
  1160.  
  1161.     /* Check for slice start code. */
  1162.  
  1163.     if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) {
  1164.  
  1165.       /* Slice start code. Parse slice header. */
  1166.  
  1167.       if (ParseSlice(vid_stream) != PARSE_OK)
  1168.         goto error;
  1169.     }
  1170.     break;
  1171.   }
  1172.  
  1173.   /* Parse next MB_QUANTUM macroblocks. */
  1174.  
  1175.   for (i = 0; i < MB_QUANTUM; i++) {
  1176.  
  1177.     /* Check to see if actually a startcode and not a macroblock. */
  1178.  
  1179.     if (!next_bits(23, 0x00000000)) {
  1180.  
  1181.       /* Not start code. Parse Macroblock. */
  1182.  
  1183.       if (ParseMacroBlock(vid_stream) != PARSE_OK)
  1184.         goto error;
  1185.  
  1186. #ifdef ANALYSIS
  1187.       if (showmb_flag) {
  1188.         DoDitherImage(vid_stream->current->luminance,
  1189.                   vid_stream->current->Cr,
  1190.                   vid_stream->current->Cb, vid_stream->current->display,
  1191.                   vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  1192.         ExecuteDisplay(vid_stream);
  1193.       }
  1194. #endif
  1195.  
  1196.     } else {
  1197.  
  1198.       /* Not macroblock, actually start code. Get start code. */
  1199.  
  1200.       next_start_code();
  1201.       show_bits32(data);
  1202.  
  1203.       /*
  1204.        * If start code is outside range of slice start codes, frame is
  1205.        * complete, display frame.
  1206.        */
  1207.  
  1208.       if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
  1209.  
  1210. #ifdef ANALYSIS
  1211.     EndTime();
  1212.     stat_a[0].totsize += bitCountRead() - pictureSizeCount;
  1213.     if (showEachFlag) {
  1214.       PrintOneStat();
  1215.     };
  1216.  
  1217.     CollectStats();
  1218. #endif
  1219.  
  1220.     DoPictureDisplay(vid_stream);
  1221.       }
  1222.       goto done;
  1223.     }
  1224.   }
  1225.  
  1226.   /* Check if we just finished a picture on the MB_QUANTUMth macroblock */
  1227.   if (next_bits(23, 0x00000000)) {
  1228.     next_start_code();
  1229.     show_bits32(data);
  1230.     if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
  1231.  
  1232. #ifdef ANALYSIS
  1233.     EndTime();
  1234.     stat_a[0].totsize += bitCountRead() - pictureSizeCount;
  1235.     if (showEachFlag) {
  1236.       PrintOneStat();
  1237.     };
  1238.  
  1239.     CollectStats();
  1240. #endif
  1241.  
  1242.     DoPictureDisplay(vid_stream);
  1243.     }
  1244.   }
  1245.  
  1246.   /* Return pointer to video stream structure. */
  1247.  
  1248.   goto done;
  1249.  
  1250. error:
  1251.   fprintf(stderr, "Error!!!!\n");
  1252.   next_start_code();
  1253.   goto done;
  1254.  
  1255. done:
  1256.  
  1257.   /* Copy global bit i/o variables back into vid_stream. */
  1258.  
  1259.   vid_stream->buffer = bitBuffer;
  1260.   vid_stream->buf_length = bufLength;
  1261.   vid_stream->bit_offset = bitOffset;
  1262.  
  1263.   return vid_stream;
  1264.  
  1265. }
  1266.  
  1267.  
  1268.  
  1269.  
  1270. /*
  1271.  *--------------------------------------------------------------
  1272.  *
  1273.  * ParseSeqHead --
  1274.  *
  1275.  *      Assumes bit stream is at the begining of the sequence
  1276.  *      header start code. Parses off the sequence header.
  1277.  *
  1278.  * Results:
  1279.  *      Fills the vid_stream structure with values derived and
  1280.  *      decoded from the sequence header. Allocates the pict image
  1281.  *      structures based on the dimensions of the image space
  1282.  *      found in the sequence header.
  1283.  *
  1284.  * Side effects:
  1285.  *      Bit stream irreversibly parsed off.
  1286.  *
  1287.  *--------------------------------------------------------------
  1288.  */
  1289. static int
  1290. ParseSeqHead(vid_stream)
  1291.   VidStream *vid_stream;
  1292. {
  1293.  
  1294.   unsigned int data;
  1295.   int i;
  1296.  
  1297.   /* Flush off sequence start code. */
  1298.  
  1299.   flush_bits32;
  1300.  
  1301.   /* Get horizontal size of image space. */
  1302.  
  1303.   get_bits12(data);
  1304.   vid_stream->h_size = data;
  1305.  
  1306.   /* Get vertical size of image space. */
  1307.  
  1308.   get_bits12(data);
  1309.   vid_stream->v_size = data;
  1310.  
  1311.   /* Calculate macroblock width and height of image space. */
  1312.  
  1313.   vid_stream->mb_width = (vid_stream->h_size + 15) / 16;
  1314.   vid_stream->mb_height = (vid_stream->v_size + 15) / 16;
  1315.  
  1316.   /* If dither type is MBORDERED allocate ditherFlags. */
  1317.  
  1318.   if (ditherType == MBORDERED_DITHER) {
  1319.     ditherFlags = (char *) malloc(vid_stream->mb_width*vid_stream->mb_height);
  1320.   }
  1321.  
  1322.   /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */
  1323.  
  1324.   lmaxx = vid_stream->mb_width*16-1;
  1325.   lmaxy = vid_stream->mb_height*16-1;
  1326.   cmaxx = vid_stream->mb_width*8-1;
  1327.   cmaxy = vid_stream->mb_height*8-1;
  1328.  
  1329.   /*
  1330.    * Initialize ring buffer of pict images now that dimensions of image space
  1331.    * are known.
  1332.    */
  1333.  
  1334. #ifdef SH_MEM
  1335.   if (display != NULL) {
  1336.     InstallXErrorHandler();
  1337.   }
  1338. #endif
  1339.  
  1340.   if (vid_stream->ring[0] == NULL) {
  1341.     for (i = 0; i < RING_BUF_SIZE; i++) {
  1342.       vid_stream->ring[i] = NewPictImage(vid_stream->mb_width * 16,
  1343.                      vid_stream->mb_height * 16);
  1344.     }
  1345.   }
  1346. #ifdef SH_MEM
  1347.   if (display != NULL) {
  1348.     DeInstallXErrorHandler();
  1349.   }
  1350. #endif
  1351.  
  1352.   /* Parse of aspect ratio code. */
  1353.  
  1354.   get_bits4(data);
  1355.   vid_stream->aspect_ratio = (unsigned char) data;
  1356.  
  1357.   /* Parse off picture rate code. */
  1358.  
  1359.   get_bits4(data);
  1360.   vid_stream->picture_rate = (unsigned char) data;
  1361.  
  1362.   /* Parse off bit rate. */
  1363.  
  1364.   get_bits18(data);
  1365.   vid_stream->bit_rate = data;
  1366.  
  1367.   /* Flush marker bit. */
  1368.  
  1369.   flush_bits(1);
  1370.  
  1371.   /* Parse off vbv buffer size. */
  1372.  
  1373.   get_bits10(data);
  1374.   vid_stream->vbv_buffer_size = data;
  1375.  
  1376. #ifdef not_def
  1377.   /* Lets not bother with this.  Only increases memory image */
  1378.   if (data*1024>vid_stream->max_buf_length) {
  1379.     unsigned int *newbuf;
  1380.     int sz=1024*data+1;
  1381.     /* If they actually want a bigger buffer than we default to,
  1382.        let them have it! (if we can) */
  1383.     newbuf = (unsigned int *) realloc(vid_stream->buf_start, (unsigned int) 4*sz);
  1384.     if (newbuf!=(unsigned int *)NULL) {
  1385.       vid_stream->max_buf_length=sz;
  1386.       bitBuffer=(bitBuffer-vid_stream->buf_start)+newbuf;
  1387.       vid_stream->buf_start=newbuf;
  1388.     }}
  1389. #endif
  1390.  
  1391.   /* Parse off contrained parameter flag. */
  1392.  
  1393.   get_bits1(data);
  1394.   if (data) {
  1395.     vid_stream->const_param_flag = TRUE;
  1396.   } else
  1397.     vid_stream->const_param_flag = FALSE;
  1398.  
  1399.   /*
  1400.    * If intra_quant_matrix_flag set, parse off intra quant matrix values.
  1401.    */
  1402.  
  1403.   get_bits1(data);
  1404.   if (data) {
  1405.     for (i = 0; i < 64; i++) {
  1406.       get_bits8(data);
  1407.  
  1408.       vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  1409.     (unsigned char) data;
  1410.     }
  1411.   }
  1412.   /*
  1413.    * If non intra quant matrix flag set, parse off non intra quant matrix
  1414.    * values.
  1415.    */
  1416.  
  1417.   get_bits1(data);
  1418.   if (data) {
  1419.     for (i = 0; i < 64; i++) {
  1420.       get_bits8(data);
  1421.  
  1422.       vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  1423.     (unsigned char) data;
  1424.     }
  1425.   }
  1426.   /* Go to next start code. */
  1427.  
  1428.   next_start_code();
  1429.  
  1430.   /*
  1431.    * If next start code is extension start code, parse off extension data.
  1432.    */
  1433.  
  1434.   if (next_bits(32, EXT_START_CODE)) {
  1435.     flush_bits32;
  1436.     if (vid_stream->ext_data != NULL) {
  1437.       free(vid_stream->ext_data);
  1438.       vid_stream->ext_data = NULL;
  1439.     }
  1440.     vid_stream->ext_data = get_ext_data();
  1441.   }
  1442.   /* If next start code is user start code, parse off user data. */
  1443.  
  1444.   if (next_bits(32, USER_START_CODE)) {
  1445.     flush_bits32;
  1446.     if (vid_stream->user_data != NULL) {
  1447.       free(vid_stream->user_data);
  1448.       vid_stream->user_data = NULL;
  1449.     }
  1450.     vid_stream->user_data = get_ext_data();
  1451.   }
  1452.   return PARSE_OK;
  1453. }
  1454.  
  1455.  
  1456.  
  1457. /*
  1458.  *--------------------------------------------------------------
  1459.  *
  1460.  * ParseGOP --
  1461.  *
  1462.  *      Parses of group of pictures header from bit stream
  1463.  *      associated with vid_stream.
  1464.  *
  1465.  * Results:
  1466.  *      Values in gop header placed into video stream structure.
  1467.  *
  1468.  * Side effects:
  1469.  *      Bit stream irreversibly parsed.
  1470.  *
  1471.  *--------------------------------------------------------------
  1472.  */
  1473.  
  1474. static int
  1475. ParseGOP(vid_stream)
  1476.   VidStream *vid_stream;
  1477. {
  1478.   unsigned int data;
  1479.  
  1480.   /* Flush group of pictures start code. */
  1481.  
  1482.   flush_bits32;
  1483.  
  1484.   /* Parse off drop frame flag. */
  1485.  
  1486.   get_bits1(data);
  1487.   if (data) {
  1488.     vid_stream->group.drop_flag = TRUE;
  1489.   } else
  1490.     vid_stream->group.drop_flag = FALSE;
  1491.  
  1492.   /* Parse off hour component of time code. */
  1493.  
  1494.   get_bits5(data);
  1495.   vid_stream->group.tc_hours = data;
  1496.  
  1497.   /* Parse off minute component of time code. */
  1498.  
  1499.   get_bits6(data);
  1500.   vid_stream->group.tc_minutes = data;
  1501.  
  1502.   /* Flush marker bit. */
  1503.  
  1504.   flush_bits(1);
  1505.  
  1506.   /* Parse off second component of time code. */
  1507.  
  1508.   get_bits6(data);
  1509.   vid_stream->group.tc_seconds = data;
  1510.  
  1511.   /* Parse off picture count component of time code. */
  1512.  
  1513.   get_bits6(data);
  1514.   vid_stream->group.tc_pictures = data;
  1515.  
  1516.   /* Parse off closed gop and broken link flags. */
  1517.  
  1518.   get_bits2(data);
  1519.   if (data > 1) {
  1520.     vid_stream->group.closed_gop = TRUE;
  1521.     if (data > 2) {
  1522.       vid_stream->group.broken_link = TRUE;
  1523.     } else
  1524.       vid_stream->group.broken_link = FALSE;
  1525.   } else {
  1526.     vid_stream->group.closed_gop = FALSE;
  1527.     if (data) {
  1528.       vid_stream->group.broken_link = TRUE;
  1529.     } else
  1530.       vid_stream->group.broken_link = FALSE;
  1531.   }
  1532.  
  1533.   /* Goto next start code. */
  1534.  
  1535.   next_start_code();
  1536.  
  1537.   /* If next start code is extension data, parse off extension data. */
  1538.  
  1539.   if (next_bits(32, EXT_START_CODE)) {
  1540.     flush_bits32;
  1541.     if (vid_stream->group.ext_data != NULL) {
  1542.       free(vid_stream->group.ext_data);
  1543.       vid_stream->group.ext_data = NULL;
  1544.     }
  1545.     vid_stream->group.ext_data = get_ext_data();
  1546.   }
  1547.   /* If next start code is user data, parse off user data. */
  1548.  
  1549.   if (next_bits(32, USER_START_CODE)) {
  1550.     flush_bits32;
  1551.     if (vid_stream->group.user_data != NULL) {
  1552.       free(vid_stream->group.user_data);
  1553.       vid_stream->group.user_data = NULL;
  1554.     }
  1555.     vid_stream->group.user_data = get_ext_data();
  1556.   }
  1557.   return PARSE_OK;
  1558. }
  1559.  
  1560.  
  1561.  
  1562. /*
  1563.  *--------------------------------------------------------------
  1564.  *
  1565.  * ParsePicture --
  1566.  *
  1567.  *      Parses picture header. Marks picture to be presented
  1568.  *      at particular time given a time stamp.
  1569.  *
  1570.  * Results:
  1571.  *      Values from picture header put into video stream structure.
  1572.  *
  1573.  * Side effects:
  1574.  *      Bit stream irreversibly parsed.
  1575.  *
  1576.  *--------------------------------------------------------------
  1577.  */
  1578.  
  1579. static int
  1580. ParsePicture(vid_stream, time_stamp)
  1581.   VidStream *vid_stream;
  1582.   TimeStamp time_stamp;
  1583. {
  1584.   unsigned int data;
  1585.   int i;
  1586.  
  1587.   /* Flush header start code. */
  1588.   flush_bits32;
  1589.  
  1590.   /* Parse off temporal reference. */
  1591.   get_bits10(data);
  1592.   vid_stream->picture.temp_ref = data;
  1593.  
  1594.   /* Parse of picture type. */
  1595.   get_bits3(data);
  1596.   vid_stream->picture.code_type = data;
  1597.  
  1598.   if ((vid_stream->picture.code_type == B_TYPE) &&
  1599.       (No_B_Flag ||
  1600.        (vid_stream->future == NULL) ||
  1601.        ((vid_stream->past == NULL) && !(vid_stream->group.closed_gop))))
  1602.     /* According to 2-D.5.1 (p D-18) this is ok, if the refereneces are OK */
  1603.     return SKIP_PICTURE;
  1604.  
  1605.   if ((vid_stream->picture.code_type == P_TYPE) &&
  1606.       (No_P_Flag || (vid_stream->future == NULL)))
  1607.     return SKIP_PICTURE;
  1608.  
  1609. #ifdef ANALYSIS
  1610.   StartTime();
  1611.   stat_a[0].frametype = vid_stream->picture.code_type;
  1612.   stat_a[0].number = 1;
  1613.   stat_a[0].totsize = 45;
  1614.   pictureSizeCount = bitCountRead();
  1615. #endif
  1616.  
  1617.   /* Parse off vbv buffer delay value. */
  1618.   get_bits16(data);
  1619.   vid_stream->picture.vbv_delay = data;
  1620.  
  1621.   /* If P or B type frame... */
  1622.  
  1623.   if ((vid_stream->picture.code_type == 2) || (vid_stream->picture.code_type == 3)) {
  1624.  
  1625.     /* Parse off forward vector full pixel flag. */
  1626.     get_bits1(data);
  1627.     if (data)
  1628.       vid_stream->picture.full_pel_forw_vector = TRUE;
  1629.     else
  1630.       vid_stream->picture.full_pel_forw_vector = FALSE;
  1631.  
  1632.     /* Parse of forw_r_code. */
  1633.     get_bits3(data);
  1634.  
  1635.     /* Decode forw_r_code into forw_r_size and forw_f. */
  1636.  
  1637.     vid_stream->picture.forw_r_size = data - 1;
  1638.     vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size);
  1639.   }
  1640.   /* If B type frame... */
  1641.  
  1642.   if (vid_stream->picture.code_type == 3) {
  1643.  
  1644.     /* Parse off back vector full pixel flag. */
  1645.     get_bits1(data);
  1646.     if (data)
  1647.       vid_stream->picture.full_pel_back_vector = TRUE;
  1648.     else
  1649.       vid_stream->picture.full_pel_back_vector = FALSE;
  1650.  
  1651.     /* Parse off back_r_code. */
  1652.     get_bits3(data);
  1653.  
  1654.     /* Decode back_r_code into back_r_size and back_f. */
  1655.  
  1656.     vid_stream->picture.back_r_size = data - 1;
  1657.     vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size);
  1658.   }
  1659.   /* Get extra bit picture info. */
  1660.  
  1661.   if (vid_stream->picture.extra_info != NULL) {
  1662.     free(vid_stream->picture.extra_info);
  1663.     vid_stream->picture.extra_info = NULL;
  1664.   }
  1665.   vid_stream->picture.extra_info = get_extra_bit_info();
  1666.  
  1667.   /* Goto next start code. */
  1668.   next_start_code();
  1669.  
  1670.   /* If start code is extension start code, parse off extension data. */
  1671.  
  1672.   if (next_bits(32, EXT_START_CODE)) {
  1673.     flush_bits32;
  1674.  
  1675.     if (vid_stream->picture.ext_data != NULL) {
  1676.       free(vid_stream->picture.ext_data);
  1677.       vid_stream->picture.ext_data = NULL;
  1678.     }
  1679.     vid_stream->picture.ext_data = get_ext_data();
  1680.   }
  1681.   /* If start code is user start code, parse off user data. */
  1682.  
  1683.   if (next_bits(32, USER_START_CODE)) {
  1684.     flush_bits32;
  1685.  
  1686.     if (vid_stream->picture.user_data != NULL) {
  1687.       free(vid_stream->picture.user_data);
  1688.       vid_stream->picture.user_data = NULL;
  1689.     }
  1690.     vid_stream->picture.user_data = get_ext_data();
  1691.   }
  1692.   /* Find a pict image structure in ring buffer not currently locked. */
  1693.  
  1694.   i = 0;
  1695.  
  1696.   while (vid_stream->ring[i]->locked != 0) {
  1697.     if (++i >= RING_BUF_SIZE) {
  1698.       perror("Fatal error. Ring buffer full.");
  1699.       exit(1);
  1700.     }
  1701.   }
  1702.  
  1703.   /* Set current pict image structure to the one just found in ring. */
  1704.  
  1705.   vid_stream->current = vid_stream->ring[i];
  1706.  
  1707.   /* Set time stamp. */
  1708.  
  1709.   vid_stream->current->show_time = time_stamp;
  1710.  
  1711.   /* Reset past macroblock address field. */
  1712.  
  1713.   vid_stream->mblock.past_mb_addr = -1;
  1714.  
  1715.   return PARSE_OK;
  1716. }
  1717.  
  1718.  
  1719.  
  1720. /*
  1721.  *--------------------------------------------------------------
  1722.  *
  1723.  * ParseSlice --
  1724.  *
  1725.  *      Parses off slice header.
  1726.  *
  1727.  * Results:
  1728.  *      Values found in slice header put into video stream structure.
  1729.  *
  1730.  * Side effects:
  1731.  *      Bit stream irreversibly parsed.
  1732.  *
  1733.  *--------------------------------------------------------------
  1734.  */
  1735.  
  1736. static int
  1737. ParseSlice(vid_stream)
  1738.   VidStream *vid_stream;
  1739. {
  1740.   unsigned int data;
  1741.  
  1742.   /* Flush slice start code. */
  1743.  
  1744.   flush_bits(24);
  1745.  
  1746.   /* Parse off slice vertical position. */
  1747.  
  1748.   get_bits8(data);
  1749.   vid_stream->slice.vert_pos = data;
  1750.  
  1751.   /* Parse off quantization scale. */
  1752.  
  1753.   get_bits5(data);
  1754.   vid_stream->slice.quant_scale = data;
  1755.  
  1756.   /* Parse off extra bit slice info. */
  1757.  
  1758.   if (vid_stream->slice.extra_info != NULL) {
  1759.     free(vid_stream->slice.extra_info);
  1760.     vid_stream->slice.extra_info = NULL;
  1761.   }
  1762.   vid_stream->slice.extra_info = get_extra_bit_info();
  1763.  
  1764.   /* Reset past intrablock address. */
  1765.  
  1766.   vid_stream->mblock.past_intra_addr = -2;
  1767.  
  1768.   /* Reset previous recon motion vectors. */
  1769.  
  1770.   vid_stream->mblock.recon_right_for_prev = 0;
  1771.   vid_stream->mblock.recon_down_for_prev = 0;
  1772.   vid_stream->mblock.recon_right_back_prev = 0;
  1773.   vid_stream->mblock.recon_down_back_prev = 0;
  1774.  
  1775.   /* Reset macroblock address. */
  1776.  
  1777.   vid_stream->mblock.mb_address = ((vid_stream->slice.vert_pos - 1) *
  1778.                    vid_stream->mb_width) - 1;
  1779.  
  1780.   /* Reset past dct dc y, cr, and cb values. */
  1781.  
  1782.   vid_stream->block.dct_dc_y_past = 1024 << 3;
  1783.   vid_stream->block.dct_dc_cr_past = 1024 << 3;
  1784.   vid_stream->block.dct_dc_cb_past = 1024 << 3;
  1785.  
  1786.   return PARSE_OK;
  1787. }
  1788.  
  1789.  
  1790.  
  1791. /*
  1792.  *--------------------------------------------------------------
  1793.  *
  1794.  * ParseMacroBlock --
  1795.  *
  1796.  *      Parseoff macroblock. Reconstructs DCT values. Applies
  1797.  *      inverse DCT, reconstructs motion vectors, calculates and
  1798.  *      set pixel values for macroblock in current pict image
  1799.  *      structure.
  1800.  *
  1801.  * Results:
  1802.  *      Here's where everything really happens. Welcome to the
  1803.  *      heart of darkness.
  1804.  *
  1805.  * Side effects:
  1806.  *      Bit stream irreversibly parsed off.
  1807.  *
  1808.  *--------------------------------------------------------------
  1809.  */
  1810.  
  1811. static int
  1812. ParseMacroBlock(vid_stream)
  1813.   VidStream *vid_stream;
  1814. {
  1815.   int addr_incr;
  1816.   unsigned int data;
  1817.   int mask, i, recon_right_for, recon_down_for, recon_right_back,
  1818.       recon_down_back;
  1819.   int zero_block_flag;
  1820.   BOOLEAN mb_quant = 0, mb_motion_forw = 0, mb_motion_back = 0, 
  1821.       mb_pattern = 0;
  1822.   int no_dith_flag = 0;
  1823.  
  1824. #ifdef ANALYSIS
  1825.   mbSizeCount = bitCountRead();
  1826. #endif
  1827.  
  1828.   /*
  1829.    * Parse off macroblock address increment and add to macroblock address.
  1830.    */
  1831.   do {
  1832.     unsigned int ind;                       
  1833.     show_bits11(ind);                       
  1834.     DecodeMBAddrInc(addr_incr);
  1835.     if (mb_addr_inc[ind].num_bits==0) addr_incr = 1;  /* error occured */
  1836.     if (addr_incr == MB_ESCAPE) {
  1837.       vid_stream->mblock.mb_address += 33;
  1838.       addr_incr = MB_STUFFING;
  1839.     }
  1840.   } while (addr_incr == MB_STUFFING);
  1841.   vid_stream->mblock.mb_address += addr_incr;
  1842.  
  1843.   if (vid_stream->mblock.mb_address > (vid_stream->mb_height *
  1844.                        vid_stream->mb_width - 1))
  1845.     return SKIP_TO_START_CODE;
  1846.  
  1847.   /*
  1848.    * If macroblocks have been skipped, process skipped macroblocks.
  1849.    */
  1850.  
  1851.   if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) {
  1852.     if (vid_stream->picture.code_type == P_TYPE)
  1853.       ProcessSkippedPFrameMBlocks(vid_stream);
  1854.     else if (vid_stream->picture.code_type == B_TYPE)
  1855.       ProcessSkippedBFrameMBlocks(vid_stream);
  1856.   }
  1857.   /* Set past macroblock address to current macroblock address. */
  1858.   vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address;
  1859.  
  1860.   /* Based on picture type decode macroblock type. */
  1861.   switch (vid_stream->picture.code_type) {
  1862.   case I_TYPE:
  1863.     DecodeMBTypeI(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1864.           vid_stream->mblock.mb_intra);
  1865.     break;
  1866.  
  1867.   case P_TYPE:
  1868.     DecodeMBTypeP(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1869.           vid_stream->mblock.mb_intra);
  1870.     break;
  1871.  
  1872.   case B_TYPE:
  1873.     DecodeMBTypeB(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1874.           vid_stream->mblock.mb_intra);
  1875.     break;
  1876.   case D_TYPE:
  1877.     fprintf(stderr, "ERROR:  MPEG-1 Streams with D-frames are not supported\n");
  1878.     exit(1);
  1879.   }
  1880.  
  1881.   /* If quantization flag set, parse off new quantization scale. */
  1882.  
  1883.   if (mb_quant == TRUE) {
  1884.     get_bits5(data);
  1885.     vid_stream->slice.quant_scale = data;
  1886.   }
  1887.   /* If forward motion vectors exist... */
  1888.   if (mb_motion_forw == TRUE) {
  1889.  
  1890.     /* Parse off and decode horizontal forward motion vector. */
  1891.     DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code);
  1892.  
  1893.     /* If horiz. forward r data exists, parse off. */
  1894.  
  1895.     if ((vid_stream->picture.forw_f != 1) &&
  1896.     (vid_stream->mblock.motion_h_forw_code != 0)) {
  1897.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1898.       vid_stream->mblock.motion_h_forw_r = data;
  1899.     }
  1900.     /* Parse off and decode vertical forward motion vector. */
  1901.     DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code);
  1902.  
  1903.     /* If vert. forw. r data exists, parse off. */
  1904.  
  1905.     if ((vid_stream->picture.forw_f != 1) &&
  1906.     (vid_stream->mblock.motion_v_forw_code != 0)) {
  1907.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1908.       vid_stream->mblock.motion_v_forw_r = data;
  1909.     }
  1910.   }
  1911.   /* If back motion vectors exist... */
  1912.   if (mb_motion_back == TRUE) {
  1913.  
  1914.     /* Parse off and decode horiz. back motion vector. */
  1915.     DecodeMotionVectors(vid_stream->mblock.motion_h_back_code);
  1916.  
  1917.     /* If horiz. back r data exists, parse off. */
  1918.  
  1919.     if ((vid_stream->picture.back_f != 1) &&
  1920.     (vid_stream->mblock.motion_h_back_code != 0)) {
  1921.       get_bitsn(vid_stream->picture.back_r_size, data);
  1922.       vid_stream->mblock.motion_h_back_r = data;
  1923.     }
  1924.     /* Parse off and decode vert. back motion vector. */
  1925.     DecodeMotionVectors(vid_stream->mblock.motion_v_back_code);
  1926.  
  1927.     /* If vert. back r data exists, parse off. */
  1928.  
  1929.     if ((vid_stream->picture.back_f != 1) &&
  1930.     (vid_stream->mblock.motion_v_back_code != 0)) {
  1931.       get_bitsn(vid_stream->picture.back_r_size, data);
  1932.       vid_stream->mblock.motion_v_back_r = data;
  1933.     }
  1934.   }
  1935. #ifdef ANALYSIS
  1936.   if (vid_stream->mblock.mb_intra) {
  1937.     stat_a[0].i_mbnum++;
  1938.     mbCBPPtr = stat_a[0].i_mbcbp;
  1939.     mbCoeffPtr = stat_a[0].i_mbcoeff;
  1940.     mbSizePtr = &(stat_a[0].i_mbsize);
  1941.   } else if (mb_motion_back && mb_motion_forw) {
  1942.     stat_a[0].bi_mbnum++;
  1943.     mbCBPPtr = stat_a[0].bi_mbcbp;
  1944.     mbCoeffPtr = stat_a[0].bi_mbcoeff;
  1945.     mbSizePtr = &(stat_a[0].bi_mbsize);
  1946.   } else if (mb_motion_back) {
  1947.     stat_a[0].b_mbnum++;
  1948.     mbCBPPtr = stat_a[0].b_mbcbp;
  1949.     mbCoeffPtr = stat_a[0].b_mbcoeff;
  1950.     mbSizePtr = &(stat_a[0].b_mbsize);
  1951.   } else {
  1952.     stat_a[0].p_mbnum++;
  1953.     mbCBPPtr = stat_a[0].p_mbcbp;
  1954.     mbCoeffPtr = stat_a[0].p_mbcoeff;
  1955.     mbSizePtr = &(stat_a[0].p_mbsize);
  1956.   }
  1957. #endif
  1958.  
  1959.   /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
  1960.   if (mb_pattern == TRUE) {
  1961.     DecodeCBP(vid_stream->mblock.cbp);
  1962.   }
  1963.   /* Otherwise, set CBP to zero. */
  1964.   else
  1965.     vid_stream->mblock.cbp = 0;
  1966.  
  1967.  
  1968. #ifdef ANALYSIS
  1969.   mbCBPPtr[vid_stream->mblock.cbp]++;
  1970. #endif
  1971.  
  1972.   /* Reconstruct motion vectors depending on picture type. */
  1973.   if (vid_stream->picture.code_type == P_TYPE) {
  1974.  
  1975.     /*
  1976.      * If no forw motion vectors, reset previous and current vectors to 0.
  1977.      */
  1978.  
  1979.     if (!mb_motion_forw) {
  1980.       recon_right_for = 0;
  1981.       recon_down_for = 0;
  1982.       vid_stream->mblock.recon_right_for_prev = 0;
  1983.       vid_stream->mblock.recon_down_for_prev = 0;
  1984.     }
  1985.     /*
  1986.      * Otherwise, compute new forw motion vectors. Reset previous vectors to
  1987.      * current vectors.
  1988.      */
  1989.  
  1990.     else {
  1991.       ComputeForwVector(&recon_right_for, &recon_down_for);
  1992.     }
  1993.   }
  1994.   if (vid_stream->picture.code_type == B_TYPE) {
  1995.  
  1996.     /* Reset prev. and current vectors to zero if mblock is intracoded. */
  1997.  
  1998.     if (vid_stream->mblock.mb_intra) {
  1999.       vid_stream->mblock.recon_right_for_prev = 0;
  2000.       vid_stream->mblock.recon_down_for_prev = 0;
  2001.       vid_stream->mblock.recon_right_back_prev = 0;
  2002.       vid_stream->mblock.recon_down_back_prev = 0;
  2003.     } else {
  2004.       
  2005.       /* If no forw vectors, current vectors equal prev. vectors. */
  2006.       
  2007.       if (!mb_motion_forw) {
  2008.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  2009.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  2010.       }
  2011.       /*
  2012.        * Otherwise compute forw. vectors. Reset prev vectors to new values.
  2013.        */
  2014.       
  2015.       else {
  2016.     ComputeForwVector(&recon_right_for, &recon_down_for);
  2017.       }
  2018.       
  2019.       /* If no back vectors, set back vectors to prev back vectors. */
  2020.       
  2021.       if (!mb_motion_back) {
  2022.         recon_right_back = vid_stream->mblock.recon_right_back_prev;
  2023.         recon_down_back = vid_stream->mblock.recon_down_back_prev;
  2024.       }
  2025.       /* Otherwise compute new vectors and reset prev. back vectors. */
  2026.  
  2027.       else {
  2028.         ComputeBackVector(&recon_right_back, &recon_down_back);
  2029.       }
  2030.  
  2031.       /*
  2032.        * Store vector existence flags in structure for possible skipped
  2033.        * macroblocks to follow.
  2034.        */
  2035.  
  2036.       vid_stream->mblock.bpict_past_forw = mb_motion_forw;
  2037.       vid_stream->mblock.bpict_past_back = mb_motion_back;
  2038.     }
  2039.   }
  2040.  
  2041.   /* For each possible block in macroblock. */
  2042.   if (ditherType == GRAY_DITHER ||
  2043.       ditherType == GRAY2_DITHER ||
  2044.       ditherType == GRAY256_DITHER ||
  2045.       ditherType == GRAY2562_DITHER ||
  2046.       ditherType == MONO_DITHER ||
  2047.       ditherType == MONO_THRESHOLD) {
  2048.     for (mask = 32, i = 0; i < 4; mask >>= 1, i++) {
  2049.  
  2050.       /* If block exists... */
  2051.       if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  2052.         zero_block_flag = 0;
  2053.         ParseReconBlock(i);
  2054.       } else {
  2055.         zero_block_flag = 1;
  2056.       }
  2057.  
  2058.       /* If macroblock is intra coded... */
  2059.       if (vid_stream->mblock.mb_intra) {
  2060.         ReconIMBlock(vid_stream, i);
  2061.       } else if (mb_motion_forw && mb_motion_back) {
  2062.         ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  2063.             recon_right_back, recon_down_back, zero_block_flag);
  2064.       } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
  2065.         ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  2066.             zero_block_flag);
  2067.       } else if (mb_motion_back) {
  2068.         ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  2069.             zero_block_flag);
  2070.       }
  2071.     }
  2072.     /* Kill the Chrominance blocks... */
  2073.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x2)) {
  2074.         ParseAwayBlock(4);
  2075.     }
  2076.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x1)) {
  2077.         ParseAwayBlock(5);
  2078.     }
  2079.   } else {
  2080.     if ((ditherType == MBORDERED_DITHER) &&
  2081.     (vid_stream->mblock.cbp == 0) &&
  2082.     (vid_stream->picture.code_type == 3) &&
  2083.     (!vid_stream->mblock.mb_intra) &&
  2084.     (!(mb_motion_forw && mb_motion_back))) {
  2085.       MBOrderedDitherDisplayCopy(vid_stream, vid_stream->mblock.mb_address, 
  2086.              mb_motion_forw, recon_right_for, recon_down_for, 
  2087.              mb_motion_back, recon_right_back, recon_down_back,
  2088.              vid_stream->past->display, vid_stream->future->display);
  2089.       ditherFlags[vid_stream->mblock.mb_address] = 0;
  2090.       no_dith_flag = 1;
  2091.     }
  2092.     else {
  2093.       for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
  2094.     
  2095.     /* If block exists... */
  2096.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  2097.       zero_block_flag = 0;
  2098.       ParseReconBlock(i);
  2099.     } else {
  2100.       zero_block_flag = 1;
  2101.     }
  2102.     
  2103.     /* If macroblock is intra coded... */
  2104.     if (vid_stream->mblock.mb_intra) {
  2105.       ReconIMBlock(vid_stream, i);
  2106.     } else if (mb_motion_forw && mb_motion_back) {
  2107.       ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  2108.             recon_right_back, recon_down_back, zero_block_flag);
  2109.     } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
  2110.       ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  2111.                zero_block_flag);
  2112.     } else if (mb_motion_back) {
  2113.       ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  2114.                zero_block_flag);
  2115.     }
  2116.       }
  2117.     }
  2118.   }
  2119.  
  2120.   if ((ditherType == MBORDERED_DITHER) && (!no_dith_flag)) {
  2121.     if ((vid_stream->picture.code_type == 2) &&
  2122.     (vid_stream->mblock.cbp == 0) &&
  2123.     (!vid_stream->mblock.mb_intra)) {
  2124.       MBOrderedDitherDisplayCopy(vid_stream, vid_stream->mblock.mb_address,
  2125.                  1, recon_right_for, recon_down_for,
  2126.                  0, 0, 0,
  2127.                  vid_stream->future->display,
  2128.                  (unsigned char *) NULL);
  2129.       ditherFlags[vid_stream->mblock.mb_address] = 0;
  2130.     }
  2131.     else {
  2132.       ditherFlags[vid_stream->mblock.mb_address] = 1;
  2133.     }
  2134.   }
  2135.  
  2136.  
  2137.   /* If D Type picture, flush marker bit. */
  2138.   if (vid_stream->picture.code_type == 4)
  2139.     flush_bits(1);
  2140.  
  2141.   /* If macroblock was intracoded, set macroblock past intra address. */
  2142.   if (vid_stream->mblock.mb_intra)
  2143.     vid_stream->mblock.past_intra_addr =
  2144.       vid_stream->mblock.mb_address;
  2145.  
  2146. #ifdef ANALYSIS
  2147.   *mbSizePtr += bitCountRead() - mbSizeCount;
  2148. #endif
  2149.   return PARSE_OK;
  2150. }
  2151.  
  2152.  
  2153.  
  2154. /*
  2155.  *--------------------------------------------------------------
  2156.  *
  2157.  * ReconIMBlock --
  2158.  *
  2159.  *    Reconstructs intra coded macroblock.
  2160.  *
  2161.  * Results:
  2162.  *    None.
  2163.  *
  2164.  * Side effects:
  2165.  *    None.
  2166.  *
  2167.  *--------------------------------------------------------------
  2168.  */
  2169. #ifndef NDEBUG
  2170. /* If people really want to see such things, check 'em */
  2171. #define myassert(x,expression)\
  2172.   if (!(expression)) {\
  2173.   fprintf (stderr,"Bad crop value (%d) at line %d\n", x, __LINE__);\
  2174.   next_start_code(); return;}
  2175. #define assertCrop(x)    myassert(x,((x) >= -MAX_NEG_CROP) && \
  2176.                  ((x) <= 2048+MAX_NEG_CROP))
  2177. #else
  2178. #define assertCrop(x)
  2179. #endif
  2180. static void
  2181. ReconIMBlock(vid_stream, bnum)
  2182.   VidStream *vid_stream;
  2183.   int bnum;
  2184. {
  2185.   int mb_row, mb_col, row, col, row_size, rr;
  2186.   unsigned char *dest;
  2187.  
  2188.   /* Calculate macroblock row and column from address. */
  2189.  
  2190.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2191.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2192.  
  2193.  
  2194.   /* If block is luminance block... */
  2195.  
  2196.   if (bnum < 4) {
  2197.  
  2198.     /* Calculate row and col values for upper left pixel of block. */
  2199.  
  2200.     row = mb_row * 16;
  2201.     col = mb_col * 16;
  2202.     if (bnum > 1)
  2203.       row += 8;
  2204.     if (bnum % 2)
  2205.       col += 8;
  2206.  
  2207.     /* Set dest to luminance plane of current pict image. */
  2208.  
  2209.     dest = vid_stream->current->luminance;
  2210.  
  2211.     /* Establish row size. */
  2212.  
  2213.     row_size = vid_stream->mb_width * 16;
  2214.   }
  2215.   /* Otherwise if block is Cr block... */
  2216.   /* Cr first because of the earlier mixup */
  2217.  
  2218.   else if (bnum == 5) {
  2219.  
  2220.     /* Set dest to Cr plane of current pict image. */
  2221.  
  2222.     dest = vid_stream->current->Cr;
  2223.  
  2224.     /* Establish row size. */
  2225.  
  2226.     row_size = vid_stream->mb_width * 8;
  2227.  
  2228.     /* Calculate row,col for upper left pixel of block. */
  2229.  
  2230.     row = mb_row * 8;
  2231.     col = mb_col * 8;
  2232.   }
  2233.   /* Otherwise block is Cb block, and ... */
  2234.  
  2235.   else {
  2236.  
  2237.     /* Set dest to Cb plane of current pict image. */
  2238.  
  2239.     dest = vid_stream->current->Cb;
  2240.  
  2241.     /* Establish row size. */
  2242.  
  2243.     row_size = vid_stream->mb_width * 8;
  2244.  
  2245.     /* Calculate row,col for upper left pixel value of block. */
  2246.  
  2247.     row = mb_row * 8;
  2248.     col = mb_col * 8;
  2249.   }
  2250.  
  2251.   /*
  2252.    * For each pixel in block, set to cropped reconstructed value from inverse
  2253.    * dct.
  2254.    */
  2255.   {
  2256.     short *sp = &vid_stream->block.dct_recon[0][0];
  2257.     unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2258.     dest += row * row_size + col;
  2259.     for (rr = 0; rr < 4; rr++, sp += 16, dest += row_size) {
  2260.       dest[0] = cm[sp[0]];
  2261.       assertCrop(sp[0]);
  2262.       dest[1] = cm[sp[1]];
  2263.       assertCrop(sp[1]);
  2264.       dest[2] = cm[sp[2]];
  2265.       assertCrop(sp[2]);
  2266.       dest[3] = cm[sp[3]];
  2267.       assertCrop(sp[3]);
  2268.       dest[4] = cm[sp[4]];
  2269.       assertCrop(sp[4]);
  2270.       dest[5] = cm[sp[5]];
  2271.       assertCrop(sp[5]);
  2272.       dest[6] = cm[sp[6]];
  2273.       assertCrop(sp[6]);
  2274.       dest[7] = cm[sp[7]];
  2275.       assertCrop(sp[7]);
  2276.  
  2277.       dest += row_size;
  2278.       dest[0] = cm[sp[8]];
  2279.       assertCrop(sp[8]);
  2280.       dest[1] = cm[sp[9]];
  2281.       assertCrop(sp[9]);
  2282.       dest[2] = cm[sp[10]];
  2283.       assertCrop(sp[10]);
  2284.       dest[3] = cm[sp[11]];
  2285.       assertCrop(sp[11]);
  2286.       dest[4] = cm[sp[12]];
  2287.       assertCrop(sp[12]);
  2288.       dest[5] = cm[sp[13]];
  2289.       assertCrop(sp[13]);
  2290.       dest[6] = cm[sp[14]];
  2291.       assertCrop(sp[14]);
  2292.       dest[7] = cm[sp[15]];
  2293.       assertCrop(sp[15]);
  2294.     }
  2295.   }
  2296. }
  2297.  
  2298.  
  2299.  
  2300. /*
  2301.  *--------------------------------------------------------------
  2302.  *
  2303.  * ReconPMBlock --
  2304.  *
  2305.  *    Reconstructs forward predicted macroblocks.
  2306.  *
  2307.  * Results:
  2308.  *      None.
  2309.  *
  2310.  * Side effects:
  2311.  *      None.
  2312.  *
  2313.  *--------------------------------------------------------------
  2314.  */
  2315.  
  2316. static void
  2317. ReconPMBlock(vid_stream, bnum, recon_right_for, recon_down_for, zflag)
  2318.   VidStream *vid_stream;
  2319.   int bnum, recon_right_for, recon_down_for, zflag;
  2320. {
  2321.   int mb_row, mb_col, row, col, row_size, rr;
  2322.   unsigned char *dest, *past;
  2323.   static int right_for, down_for, right_half_for, down_half_for;
  2324.   unsigned char *rindex1, *rindex2, *rindex3, *rindex4;
  2325.   unsigned char *index;
  2326.   short int *blockvals;
  2327.  
  2328. #ifdef LOOSE_MPEG
  2329.   int maxx, maxy, cc;
  2330.   int illegalBlock = 0;
  2331.   int row_start, row_end, rfirst, rlast, col_start, col_end, cfirst, clast;
  2332. #endif
  2333.  
  2334.   /* Calculate macroblock row and column from address. */
  2335.  
  2336.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2337.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2338.  
  2339.   if (bnum < 4) {
  2340.  
  2341.     /* Calculate right_for, down_for motion vectors. */
  2342.  
  2343.     right_for = recon_right_for >> 1;
  2344.     down_for = recon_down_for >> 1;
  2345.     right_half_for = recon_right_for & 0x1;
  2346.     down_half_for = recon_down_for & 0x1;
  2347.  
  2348.     /* Set dest to luminance plane of current pict image. */
  2349.  
  2350.     dest = vid_stream->current->luminance;
  2351.  
  2352.     if (vid_stream->picture.code_type == B_TYPE) {
  2353.       if (vid_stream->past != NULL)
  2354.        past = vid_stream->past->luminance;
  2355.     } else {
  2356.  
  2357.       /* Set predictive frame to current future frame. */
  2358.  
  2359.       if (vid_stream->future != NULL)
  2360.         past = vid_stream->future->luminance;
  2361.     }
  2362.  
  2363.     /* Establish row size. */
  2364.  
  2365.     row_size = vid_stream->mb_width << 4;
  2366.  
  2367.     /* Calculate row,col of upper left pixel in block. */
  2368.  
  2369.     row = mb_row << 4;
  2370.     col = mb_col << 4;
  2371.     if (bnum > 1)
  2372.       row += 8;
  2373.     if (bnum % 2)
  2374.       col += 8;
  2375.  
  2376. #ifdef LOOSE_MPEG
  2377.     /* Check for block illegality. */
  2378.  
  2379.     maxx = lmaxx; maxy = lmaxy;
  2380.  
  2381.     if (row + down_for + 7 > maxy) illegalBlock |= 0x4;
  2382.     else if (row + down_for < 0)  illegalBlock |= 0x1;
  2383.     
  2384.     if (col + right_for + 7 > maxx) illegalBlock |= 0x2;
  2385.     else if (col + right_for < 0) illegalBlock |= 0x8;
  2386.  
  2387. #endif
  2388.   }
  2389.   /* Otherwise, block is NOT luminance block, ... */
  2390.  
  2391.   else {
  2392.  
  2393.     /* Construct motion vectors. */
  2394.  
  2395.     recon_right_for /= 2;
  2396.     recon_down_for /= 2;
  2397.     right_for = recon_right_for >> 1;
  2398.     down_for = recon_down_for >> 1;
  2399.     right_half_for = recon_right_for & 0x1;
  2400.     down_half_for = recon_down_for & 0x1;
  2401.  
  2402.     /* Establish row size. */
  2403.  
  2404.     row_size = vid_stream->mb_width << 3;
  2405.  
  2406.     /* Calculate row,col of upper left pixel in block. */
  2407.  
  2408.     row = mb_row << 3;
  2409.     col = mb_col << 3;
  2410.  
  2411. #ifdef LOOSE_MPEG
  2412.     /* Check for block illegality. */
  2413.  
  2414.     maxx = cmaxx; maxy = cmaxy;
  2415.  
  2416.     if (row + down_for  + 7 > maxy) illegalBlock |= 0x4;
  2417.     else if (row + down_for < 0) illegalBlock |= 0x1;
  2418.  
  2419.     if (col + right_for  + 7 > maxx) illegalBlock  |= 0x2;
  2420.     else if (col + right_for < 0) illegalBlock |= 0x8;
  2421.  
  2422. #endif
  2423.  
  2424.     /* If block is Cr block... */
  2425.     /* 5 first because order was mixed up in earlier versions */
  2426.  
  2427.     if (bnum == 5) {
  2428.  
  2429.       /* Set dest to Cr plane of current pict image. */
  2430.  
  2431.       dest = vid_stream->current->Cr;
  2432.  
  2433.       if (vid_stream->picture.code_type == B_TYPE) {
  2434.  
  2435.     if (vid_stream->past != NULL)
  2436.       past = vid_stream->past->Cr;
  2437.       } else {
  2438.     if (vid_stream->future != NULL)
  2439.       past = vid_stream->future->Cr;
  2440.       }
  2441.     }
  2442.     /* Otherwise, block is Cb block... */
  2443.  
  2444.     else {
  2445.  
  2446.       /* Set dest to Cb plane of current pict image. */
  2447.  
  2448.       dest = vid_stream->current->Cb;
  2449.  
  2450.       if (vid_stream->picture.code_type == B_TYPE) {
  2451.         if (vid_stream->past != NULL)
  2452.           past = vid_stream->past->Cb;
  2453.       } else {
  2454.         if (vid_stream->future != NULL)
  2455.           past = vid_stream->future->Cb;
  2456.       }
  2457.     }
  2458.   }
  2459.  
  2460.   /* For each pixel in block... */
  2461.  
  2462. #ifdef LOOSE_MPEG
  2463.  
  2464.   if (illegalBlock) {
  2465.     if (illegalBlock & 0x1) {
  2466.       row_start = 0;
  2467.       row_end = row+down_for+8;
  2468.       rfirst = rlast = 8 - row_end;
  2469.     }
  2470.     else if (illegalBlock & 0x4) {
  2471.       row_start = row + down_for;
  2472.       row_end = maxy+1;
  2473.       rlast = row_end - row_start - 1;
  2474.       rfirst = 0;
  2475.     }
  2476.     else {
  2477.       row_start = row+down_for;
  2478.       row_end = row_start+8;
  2479.       rfirst = 0;
  2480.     }
  2481.  
  2482.     if (illegalBlock & 0x8) {
  2483.       col_start = 0;
  2484.       col_end = col + right_for + 8;
  2485.       cfirst = clast = 8 - col_end;
  2486.     }
  2487.     else if (illegalBlock & 0x2) {
  2488.       col_start = col + right_for;
  2489.       col_end = maxx + 1;
  2490.       clast = col_end - col_start - 1;
  2491.       cfirst = 0;
  2492.     }
  2493.     else {
  2494.       col_start = col + right_for;
  2495.       col_end = col_start + 8;
  2496.       cfirst = 0;
  2497.     }
  2498.  
  2499.     for (rr = row_start; rr < row_end; rr++) {
  2500.       rindex1 = past + (rr * row_size) + col_start;
  2501.       index = dest + ((row + rfirst) * row_size) + col + cfirst;
  2502.       for (cc = col_start; cc < col_end; cc++) {
  2503.     *index++ = *rindex1++;
  2504.       }
  2505.     }
  2506.  
  2507.     if (illegalBlock & 0x1) {
  2508.       for (rr = rlast -1; rr >=0; rr--) {
  2509.         index = dest + ((row + rr) * row_size) + col;
  2510.         rindex1 = dest + ((row + rlast) * row_size) + col;
  2511.         for (cc = 0; cc < 8; cc ++) {
  2512.           *index++ = *rindex1++;
  2513.         }
  2514.       }
  2515.     }
  2516.     else if (illegalBlock & 0x4) {
  2517.       for (rr = rlast+1; rr < 8; rr++) {
  2518.         index = dest + ((row + rr) * row_size) + col;
  2519.         rindex1 = dest + ((row + rlast) * row_size) + col;
  2520.         for (cc = 0; cc < 8; cc ++) {
  2521.           *index++ = *rindex1++;
  2522.         }
  2523.       }
  2524.     }
  2525.  
  2526.     if (illegalBlock & 0x2) {
  2527.       for (cc = clast+1; cc < 8; cc++) {
  2528.         index = dest + (row * row_size) + (col + cc);
  2529.         rindex1 = dest + (row * row_size) + (col + clast);
  2530.         for (rr = 0; rr < 8; rr++) {
  2531.           *index = *rindex1;
  2532.           index += row_size;
  2533.           rindex1 += row_size;
  2534.         }
  2535.       }
  2536.     }
  2537.     else if (illegalBlock & 0x8) {
  2538.       for (cc = clast-1; cc >= 0; cc--) {
  2539.         index = dest + (row * row_size) + (col + cc);
  2540.         rindex1 = dest + (row * row_size) + (col + clast);
  2541.         for (rr = 0; rr < 8; rr++) {
  2542.           *index = *rindex1;
  2543.           index += row_size;
  2544.           rindex1 += row_size;
  2545.         }
  2546.       }
  2547.     }
  2548.  
  2549.     if (!zflag) {
  2550.       for (rr = 0; rr < 8; rr++) {
  2551.         index = dest + (row*row_size) + col;
  2552.         blockvals = &(vid_stream->block.dct_recon[rr][0]);
  2553.         index[0] += blockvals[0];
  2554.         index[1] += blockvals[1];
  2555.         index[2] += blockvals[2];
  2556.         index[3] += blockvals[3];
  2557.         index[4] += blockvals[4];
  2558.         index[5] += blockvals[5];
  2559.         index[6] += blockvals[6];
  2560.         index[7] += blockvals[7];
  2561.       }
  2562.     }
  2563.   }
  2564.   else {
  2565.  
  2566. #endif
  2567.  
  2568.     index = dest + (row * row_size) + col;
  2569.     rindex1 = past + (row + down_for) * row_size + col + right_for;
  2570.     
  2571.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2572.     
  2573.     /*
  2574.      * Calculate predictive pixel value based on motion vectors and copy to
  2575.      * dest plane.
  2576.      */
  2577.     
  2578.     if ((!down_half_for) && (!right_half_for)) {
  2579.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2580.       if (!zflag)
  2581.         for (rr = 0; rr < 4; rr++) {
  2582.           index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2583.           index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2584.           index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2585.           index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2586.           index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2587.           index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2588.           index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2589.           index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2590.           index += row_size;
  2591.           rindex1 += row_size;
  2592.       
  2593.           index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2594.           index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2595.           index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2596.           index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2597.           index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2598.           index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2599.           index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2600.           index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2601.           blockvals += 16;
  2602.           index += row_size;
  2603.           rindex1 += row_size;
  2604.         }
  2605.       else {
  2606.         if (right_for & 0x1) {
  2607.           /* No alignment, use bye copy */
  2608.           for (rr = 0; rr < 4; rr++) {
  2609.             index[0] = rindex1[0];
  2610.             index[1] = rindex1[1];
  2611.             index[2] = rindex1[2];
  2612.             index[3] = rindex1[3];
  2613.             index[4] = rindex1[4];
  2614.             index[5] = rindex1[5];
  2615.             index[6] = rindex1[6];
  2616.             index[7] = rindex1[7];
  2617.             index += row_size;
  2618.             rindex1 += row_size;
  2619.             
  2620.             index[0] = rindex1[0];
  2621.             index[1] = rindex1[1];
  2622.             index[2] = rindex1[2];
  2623.             index[3] = rindex1[3];
  2624.             index[4] = rindex1[4];
  2625.             index[5] = rindex1[5];
  2626.             index[6] = rindex1[6];
  2627.             index[7] = rindex1[7];
  2628.             index += row_size;
  2629.             rindex1 += row_size;
  2630.           }
  2631.         } else if (right_for & 0x2) {
  2632.           /* Half-word bit aligned, use 16 bit copy */
  2633.           short *src = (short *)rindex1;
  2634.           short *dest = (short *)index;
  2635.           row_size >>= 1;
  2636.           for (rr = 0; rr < 4; rr++) {
  2637.             dest[0] = src[0];
  2638.             dest[1] = src[1];
  2639.             dest[2] = src[2];
  2640.             dest[3] = src[3];
  2641.             dest += row_size;
  2642.             src += row_size;
  2643.             
  2644.             dest[0] = src[0];
  2645.             dest[1] = src[1];
  2646.             dest[2] = src[2];
  2647.             dest[3] = src[3];
  2648.             dest += row_size;
  2649.             src += row_size;
  2650.           }
  2651.         } else {
  2652.           /* Word aligned, use 32 bit copy */
  2653.           int *src = (int *)rindex1;
  2654.           int *dest = (int *)index;
  2655.           row_size >>= 2;
  2656.           for (rr = 0; rr < 4; rr++) {
  2657.             dest[0] = src[0];
  2658.             dest[1] = src[1];
  2659.             dest += row_size;
  2660.             src += row_size;
  2661.             
  2662.             dest[0] = src[0];
  2663.             dest[1] = src[1];
  2664.             dest += row_size;
  2665.             src += row_size;
  2666.           }
  2667.         }
  2668.       }
  2669.     } else {
  2670.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2671.       rindex2 = rindex1 + right_half_for + (down_half_for * row_size);
  2672.  
  2673.       /* if one of the two is zero, then quality makes no difference */
  2674.       if ((!right_half_for) || (!down_half_for) || (!qualityFlag)) {
  2675.         
  2676.         if (!zflag) {
  2677.           for (rr = 0; rr < 4; rr++) {
  2678.             index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[0]];
  2679.             index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[1]];
  2680.             index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[2]];
  2681.             index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[3]];
  2682.             index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[4]];
  2683.             index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[5]];
  2684.             index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[6]];
  2685.             index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[7]];
  2686.             index += row_size;
  2687.             rindex1 += row_size;
  2688.             rindex2 += row_size;
  2689.         
  2690.             index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[8]];
  2691.             index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[9]];
  2692.             index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[10]];
  2693.             index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[11]];
  2694.             index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[12]];
  2695.             index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[13]];
  2696.             index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[14]];
  2697.             index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[15]];
  2698.             blockvals += 16;
  2699.             index += row_size;
  2700.             rindex1 += row_size;
  2701.             rindex2 += row_size;
  2702.           }
  2703.         } else { /* zflag */
  2704.           for (rr = 0; rr < 8; rr++) {
  2705.             index[0] = (int) (rindex1[0] + rindex2[0] + 1) >> 1;
  2706.             index[1] = (int) (rindex1[1] + rindex2[1] + 1) >> 1;
  2707.             index[2] = (int) (rindex1[2] + rindex2[2] + 1) >> 1;
  2708.             index[3] = (int) (rindex1[3] + rindex2[3] + 1) >> 1;
  2709.             index[4] = (int) (rindex1[4] + rindex2[4] + 1) >> 1;
  2710.             index[5] = (int) (rindex1[5] + rindex2[5] + 1) >> 1;
  2711.             index[6] = (int) (rindex1[6] + rindex2[6] + 1) >> 1;
  2712.             index[7] = (int) (rindex1[7] + rindex2[7] + 1) >> 1;
  2713.             index += row_size;
  2714.             rindex1 += row_size;
  2715.             rindex2 += row_size;
  2716.           }
  2717.         }
  2718.       } else { /* qualityFlag on and both vectors are non-zero */
  2719.         rindex3 = rindex1 + right_half_for;
  2720.         rindex4 = rindex1 + (down_half_for * row_size);
  2721.         if (!zflag) {
  2722.           for (rr = 0; rr < 4; rr++) {
  2723.             index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[0]];
  2724.             index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[1]];
  2725.             index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[2]];
  2726.             index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[3]];
  2727.             index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[4]];
  2728.             index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[5]];
  2729.             index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[6]];
  2730.             index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[7]];
  2731.             index += row_size;
  2732.             rindex1 += row_size;
  2733.             rindex2 += row_size;
  2734.             rindex3 += row_size;
  2735.             rindex4 += row_size;
  2736.         
  2737.             index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[8]];
  2738.             index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[9]];
  2739.             index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[10]];
  2740.             index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[11]];
  2741.             index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[12]];
  2742.             index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[13]];
  2743.             index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[14]];
  2744.             index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[15]];
  2745.             blockvals += 16;
  2746.             index += row_size;
  2747.             rindex1 += row_size;
  2748.             rindex2 += row_size;
  2749.             rindex3 += row_size;
  2750.             rindex4 += row_size;
  2751.           }
  2752.         } else { /* zflag */
  2753.           for (rr = 0; rr < 8; rr++) {
  2754.             index[0] = (int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2;
  2755.             index[1] = (int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2;
  2756.             index[2] = (int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2;
  2757.             index[3] = (int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2;
  2758.             index[4] = (int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2;
  2759.             index[5] = (int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2;
  2760.             index[6] = (int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2;
  2761.             index[7] = (int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2;
  2762.             index += row_size;
  2763.             rindex1 += row_size;
  2764.             rindex2 += row_size;
  2765.             rindex3 += row_size;
  2766.             rindex4 += row_size;
  2767.           }
  2768.         }
  2769.       }
  2770.  
  2771.     }
  2772. #ifdef LOOSE_MPEG
  2773.   }
  2774. #endif
  2775. }
  2776.  
  2777.  
  2778. /*
  2779.  *--------------------------------------------------------------
  2780.  *
  2781.  * ReconBMBlock --
  2782.  *
  2783.  *    Reconstructs back predicted macroblocks.
  2784.  *
  2785.  * Results:
  2786.  *      None.
  2787.  *
  2788.  * Side effects:
  2789.  *      None.
  2790.  *
  2791.  *--------------------------------------------------------------
  2792.  */
  2793.  
  2794. static void
  2795. ReconBMBlock(vid_stream, bnum, recon_right_back, recon_down_back, zflag)
  2796.   VidStream *vid_stream;
  2797.   int bnum, recon_right_back, recon_down_back, zflag;
  2798. {
  2799.   int mb_row, mb_col, row, col, row_size, rr;
  2800.   unsigned char *dest, *future;
  2801.   int right_back, down_back, right_half_back, down_half_back;
  2802.   unsigned char *rindex1, *rindex2, *rindex3, *rindex4;
  2803.   unsigned char *index;
  2804.   short int *blockvals;
  2805.  
  2806. #ifdef LOOSE_MPEG
  2807.   int illegalBlock = 0;
  2808.   int maxx, maxy, cc;
  2809.   int row_start, row_end, rlast, rfirst, col_start, col_end, clast, cfirst;
  2810. #endif
  2811.  
  2812.   /* Calculate macroblock row and column from address. */
  2813.  
  2814.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2815.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2816.  
  2817.   /* If block is luminance block... */
  2818.  
  2819.   if (bnum < 4) {
  2820.  
  2821.     /* Calculate right_back, down_back motion vectors. */
  2822.  
  2823.     right_back = recon_right_back >> 1;
  2824.     down_back = recon_down_back >> 1;
  2825.     right_half_back = recon_right_back & 0x1;
  2826.     down_half_back = recon_down_back & 0x1;
  2827.  
  2828.     /* Set dest to luminance plane of current pict image. */
  2829.  
  2830.     dest = vid_stream->current->luminance;
  2831.  
  2832.     /*
  2833.      * If future frame exists, set future to luminance plane of future frame.
  2834.      */
  2835.  
  2836.     if (vid_stream->future != NULL)
  2837.       future = vid_stream->future->luminance;
  2838.  
  2839.     /* Establish row size. */
  2840.  
  2841.     row_size = vid_stream->mb_width << 4;
  2842.  
  2843.     /* Calculate row,col of upper left pixel in block. */
  2844.  
  2845.     row = mb_row << 4;
  2846.     col = mb_col << 4;
  2847.     if (bnum > 1)
  2848.       row += 8;
  2849.     if (bnum % 2)
  2850.       col += 8;
  2851.  
  2852. #ifdef LOOSE_MPEG
  2853.  
  2854.     /* Check for block illegality. */
  2855.  
  2856.     maxx = lmaxx; maxy = lmaxy;
  2857.  
  2858.     if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
  2859.     else if (row + down_back < 0)  illegalBlock |= 0x1;
  2860.     
  2861.     if (col + right_back + 7 > maxx) illegalBlock |= 0x2;
  2862.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2863.  
  2864. #endif
  2865.  
  2866.   }
  2867.   /* Otherwise, block is NOT luminance block, ... */
  2868.  
  2869.   else {
  2870.  
  2871.     /* Construct motion vectors. */
  2872.  
  2873.     recon_right_back /= 2;
  2874.     recon_down_back /= 2;
  2875.     right_back = recon_right_back >> 1;
  2876.     down_back = recon_down_back >> 1;
  2877.     right_half_back = recon_right_back & 0x1;
  2878.     down_half_back = recon_down_back & 0x1;
  2879.  
  2880.     /* Establish row size. */
  2881.  
  2882.     row_size = vid_stream->mb_width << 3;
  2883.  
  2884.     /* Calculate row,col of upper left pixel in block. */
  2885.  
  2886.     row = mb_row << 3;
  2887.     col = mb_col << 3;
  2888.  
  2889. #ifdef LOOSE_MPEG
  2890.  
  2891.     /* Check for block illegality. */
  2892.  
  2893.     maxx = cmaxx; maxy = cmaxy;
  2894.  
  2895.     if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
  2896.     else if (row + down_back < 0) illegalBlock |= 0x1;
  2897.  
  2898.     if (col + right_back + 7 > maxx) illegalBlock  |= 0x2;
  2899.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2900.  
  2901. #endif
  2902.  
  2903.     /* If block is Cr block... */
  2904.     /* They were switched earlier, so 5 is first - eyhung */
  2905.  
  2906.     if (bnum == 5) {
  2907.  
  2908.       /* Set dest to Cr plane of current pict image. */
  2909.  
  2910.       dest = vid_stream->current->Cr;
  2911.  
  2912.       /*
  2913.        * If future frame exists, set future to Cr plane of future image.
  2914.        */
  2915.  
  2916.       if (vid_stream->future != NULL)
  2917.     future = vid_stream->future->Cr;
  2918.     }
  2919.     /* Otherwise, block is Cb block... */
  2920.  
  2921.     else {
  2922.  
  2923.       /* Set dest to Cb plane of current pict image. */
  2924.  
  2925.       dest = vid_stream->current->Cb;
  2926.  
  2927.       /*
  2928.        * If future frame exists, set future to Cb plane of future frame.
  2929.        */
  2930.  
  2931.       if (vid_stream->future != NULL)
  2932.     future = vid_stream->future->Cb;
  2933.     }
  2934.   }
  2935.  
  2936.   /* For each pixel in block do... */
  2937.  
  2938. #ifdef LOOSE_MPEG
  2939.  
  2940.   if (illegalBlock) {
  2941.     if (illegalBlock & 0x1) {
  2942.       row_start = 0;
  2943.       row_end = row+down_back+8;
  2944.       rfirst = rlast = 8 - row_end;
  2945.     }
  2946.     else if (illegalBlock & 0x4) {
  2947.       row_start = row + down_back;
  2948.       row_end = maxy+1;
  2949.       rlast = row_end - row_start - 1;
  2950.       rfirst = 0;
  2951.     }
  2952.     else {
  2953.       row_start = row+down_back;
  2954.       row_end = row_start+8;
  2955.       rfirst = 0;
  2956.     }
  2957.  
  2958.     if (illegalBlock & 0x8) {
  2959.       col_start = 0;
  2960.       col_end = col + right_back + 8;
  2961.       cfirst = clast = 8 - col_end;
  2962.     }
  2963.     else if (illegalBlock & 0x2) {
  2964.       col_start = col + right_back;
  2965.       col_end = maxx + 1;
  2966.       clast = col_end - col_start - 1;
  2967.       cfirst = 0;
  2968.     }
  2969.     else {
  2970.       col_start = col + right_back;
  2971.       col_end = col_start + 8;
  2972.       cfirst = 0;
  2973.     }
  2974.  
  2975.     for (rr = row_start; rr < row_end; rr++) {
  2976.       rindex1 = future + (rr * row_size) + col_start;
  2977.       index = dest + ((row + rfirst) * row_size) + col + cfirst;
  2978.       for (cc = col_start; cc < col_end; cc++) {
  2979.     *index++ = *rindex1++;
  2980.       }
  2981.     }
  2982.  
  2983.     if (illegalBlock & 0x1) {
  2984.       for (rr = rlast -1; rr >=0; rr--) {
  2985.     index = dest + ((row + rr) * row_size) + col;
  2986.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2987.     for (cc = 0; cc < 8; cc ++) {
  2988.       *index++ = *rindex1++;
  2989.     }
  2990.       }
  2991.     }
  2992.     else if (illegalBlock & 0x4) {
  2993.       for (rr = rlast+1; rr < 8; rr++) {
  2994.     index = dest + ((row + rr) * row_size) + col;
  2995.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2996.     for (cc = 0; cc < 8; cc ++) {
  2997.       *index++ = *rindex1++;
  2998.     }
  2999.       }
  3000.     }
  3001.  
  3002.     if (illegalBlock & 0x2) {
  3003.       for (cc = clast+1; cc < 8; cc++) {
  3004.     index = dest + (row * row_size) + (col + cc);
  3005.     rindex1 = dest + (row * row_size) + (col + clast);
  3006.     for (rr = 0; rr < 8; rr++) {
  3007.       *index = *rindex1;
  3008.       index += row_size;
  3009.       rindex1 += row_size;
  3010.     }
  3011.       }
  3012.     }
  3013.     else if (illegalBlock & 0x8) {
  3014.       for (cc = clast-1; cc >= 0; cc--) {
  3015.     index = dest + (row * row_size) + (col + cc);
  3016.     rindex1 = dest + (row * row_size) + (col + clast);
  3017.     for (rr = 0; rr < 8; rr++) {
  3018.       *index = *rindex1;
  3019.       index += row_size;
  3020.       rindex1 += row_size;
  3021.     }
  3022.       }
  3023.     }
  3024.  
  3025.     if (!zflag) {
  3026.       for (rr = 0; rr < 8; rr++) {
  3027.     index = dest + (row*row_size) + col;
  3028.     blockvals = &(vid_stream->block.dct_recon[rr][0]);
  3029.     index[0] += blockvals[0];
  3030.     index[1] += blockvals[1];
  3031.     index[2] += blockvals[2];
  3032.     index[3] += blockvals[3];
  3033.     index[4] += blockvals[4];
  3034.     index[5] += blockvals[5];
  3035.     index[6] += blockvals[6];
  3036.     index[7] += blockvals[7];
  3037.       }
  3038.     }
  3039.   }
  3040.   else {
  3041.  
  3042. #endif
  3043.     
  3044.     index = dest + (row * row_size) + col;
  3045.     rindex1 = future + (row + down_back) * row_size + col + right_back;
  3046.  
  3047.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  3048.  
  3049.     if ((!right_half_back) && (!down_half_back)) {
  3050.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  3051.       if (!zflag)
  3052.     for (rr = 0; rr < 4; rr++) {
  3053.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  3054.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  3055.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  3056.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  3057.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  3058.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  3059.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  3060.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  3061.       index += row_size;
  3062.       rindex1 += row_size;
  3063.       
  3064.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  3065.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  3066.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  3067.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  3068.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  3069.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  3070.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  3071.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  3072.       blockvals += 16;
  3073.       index += row_size;
  3074.       rindex1 += row_size;
  3075.     }
  3076.       else {
  3077.     if (right_back & 0x1) {
  3078.       /* No alignment, use bye copy */
  3079.       for (rr = 0; rr < 4; rr++) {
  3080.         index[0] = rindex1[0];
  3081.         index[1] = rindex1[1];
  3082.         index[2] = rindex1[2];
  3083.         index[3] = rindex1[3];
  3084.         index[4] = rindex1[4];
  3085.         index[5] = rindex1[5];
  3086.         index[6] = rindex1[6];
  3087.         index[7] = rindex1[7];
  3088.         index += row_size;
  3089.         rindex1 += row_size;
  3090.         
  3091.         index[0] = rindex1[0];
  3092.         index[1] = rindex1[1];
  3093.         index[2] = rindex1[2];
  3094.         index[3] = rindex1[3];
  3095.         index[4] = rindex1[4];
  3096.         index[5] = rindex1[5];
  3097.         index[6] = rindex1[6];
  3098.         index[7] = rindex1[7];
  3099.         index += row_size;
  3100.         rindex1 += row_size;
  3101.       }
  3102.     } else if (right_back & 0x2) {
  3103.       /* Half-word bit aligned, use 16 bit copy */
  3104.       short *src = (short *)rindex1;
  3105.       short *dest = (short *)index;
  3106.       row_size >>= 1;
  3107.       for (rr = 0; rr < 4; rr++) {
  3108.         dest[0] = src[0];
  3109.         dest[1] = src[1];
  3110.         dest[2] = src[2];
  3111.         dest[3] = src[3];
  3112.         dest += row_size;
  3113.         src += row_size;
  3114.         
  3115.         dest[0] = src[0];
  3116.         dest[1] = src[1];
  3117.         dest[2] = src[2];
  3118.         dest[3] = src[3];
  3119.         dest += row_size;
  3120.         src += row_size;
  3121.       }
  3122.     } else {
  3123.       /* Word aligned, use 32 bit copy */
  3124.       int *src = (int *)rindex1;
  3125.       int *dest = (int *)index;
  3126.       row_size >>= 2;
  3127.       for (rr = 0; rr < 4; rr++) {
  3128.         dest[0] = src[0];
  3129.         dest[1] = src[1];
  3130.         dest += row_size;
  3131.         src += row_size;
  3132.         
  3133.         dest[0] = src[0];
  3134.         dest[1] = src[1];
  3135.         dest += row_size;
  3136.         src += row_size;
  3137.       }
  3138.     }
  3139.       }
  3140.     } else {
  3141.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  3142.       rindex2 = rindex1 + right_half_back + (down_half_back * row_size);
  3143.       if (!qualityFlag) {
  3144.         
  3145.         if (!zflag) {
  3146.           for (rr = 0; rr < 4; rr++) {
  3147.             index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[0]];
  3148.             index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[1]];
  3149.             index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[2]];
  3150.             index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[3]];
  3151.             index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[4]];
  3152.             index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[5]];
  3153.             index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[6]];
  3154.             index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[7]];
  3155.             index += row_size;
  3156.             rindex1 += row_size;
  3157.             rindex2 += row_size;
  3158.         
  3159.             index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[8]];
  3160.             index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[9]];
  3161.             index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[10]];
  3162.             index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[11]];
  3163.             index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[12]];
  3164.             index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[13]];
  3165.             index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[14]];
  3166.             index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[15]];
  3167.             blockvals += 16;
  3168.             index += row_size;
  3169.             rindex1 += row_size;
  3170.             rindex2 += row_size;
  3171.           }
  3172.         } else { /* zflag */
  3173.           for (rr = 0; rr < 8; rr++) {
  3174.             index[0] = (int) (rindex1[0] + rindex2[0] + 1) >> 1;
  3175.             index[1] = (int) (rindex1[1] + rindex2[1] + 1) >> 1;
  3176.             index[2] = (int) (rindex1[2] + rindex2[2] + 1) >> 1;
  3177.             index[3] = (int) (rindex1[3] + rindex2[3] + 1) >> 1;
  3178.             index[4] = (int) (rindex1[4] + rindex2[4] + 1) >> 1;
  3179.             index[5] = (int) (rindex1[5] + rindex2[5] + 1) >> 1;
  3180.             index[6] = (int) (rindex1[6] + rindex2[6] + 1) >> 1;
  3181.             index[7] = (int) (rindex1[7] + rindex2[7] + 1) >> 1;
  3182.             index += row_size;
  3183.             rindex1 += row_size;
  3184.             rindex2 += row_size;
  3185.           }
  3186.         }
  3187.       } else { /* qualityFlag on */
  3188.         rindex3 = rindex1 + right_half_back;
  3189.         rindex4 = rindex1 + (down_half_back * row_size);
  3190.         if (!zflag) {
  3191.           for (rr = 0; rr < 4; rr++) {
  3192.             index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[0]];
  3193.             index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[1]];
  3194.             index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[2]];
  3195.             index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[3]];
  3196.             index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[4]];
  3197.             index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[5]];
  3198.             index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[6]];
  3199.             index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[7]];
  3200.             index += row_size;
  3201.             rindex1 += row_size;
  3202.             rindex2 += row_size;
  3203.             rindex3 += row_size;
  3204.             rindex4 += row_size;
  3205.         
  3206.             index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[8]];
  3207.             index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[9]];
  3208.             index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[10]];
  3209.             index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[11]];
  3210.             index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[12]];
  3211.             index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[13]];
  3212.             index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[14]];
  3213.             index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[15]];
  3214.             blockvals += 16;
  3215.             index += row_size;
  3216.             rindex1 += row_size;
  3217.             rindex2 += row_size;
  3218.             rindex3 += row_size;
  3219.             rindex4 += row_size;
  3220.           }
  3221.         } else { /* zflag */
  3222.           for (rr = 0; rr < 8; rr++) {
  3223.             index[0] = (int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2;
  3224.             index[1] = (int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2;
  3225.             index[2] = (int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2;
  3226.             index[3] = (int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2;
  3227.             index[4] = (int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2;
  3228.             index[5] = (int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2;
  3229.             index[6] = (int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2;
  3230.             index[7] = (int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2;
  3231.             index += row_size;
  3232.             rindex1 += row_size;
  3233.             rindex2 += row_size;
  3234.             rindex3 += row_size;
  3235.             rindex4 += row_size;
  3236.           }
  3237.         }
  3238.       }
  3239.  
  3240.     }
  3241. #ifdef LOOSE_MPEG
  3242.   }
  3243. #endif
  3244. }
  3245.  
  3246.  
  3247. /*
  3248.  *--------------------------------------------------------------
  3249.  *
  3250.  * ReconBiMBlock --
  3251.  *
  3252.  *    Reconstructs bidirectionally predicted macroblocks.
  3253.  *
  3254.  * Results:
  3255.  *      None.
  3256.  *
  3257.  * Side effects:
  3258.  *      None.
  3259.  *
  3260.  *--------------------------------------------------------------
  3261.  */
  3262.  
  3263. static void
  3264. ReconBiMBlock(vid_stream, bnum, recon_right_for, recon_down_for,
  3265.           recon_right_back, recon_down_back, zflag)
  3266.   VidStream *vid_stream;
  3267.   int bnum, recon_right_for, recon_down_for, recon_right_back, recon_down_back;
  3268.   int zflag;
  3269. {
  3270.   int mb_row, mb_col, row, col, row_size, rr;
  3271.   unsigned char *dest, *past=NULL, *future=NULL;
  3272.   int right_for, down_for, right_half_for, down_half_for;
  3273.   int right_back, down_back, right_half_back, down_half_back;
  3274.   unsigned char *index, *rindex1, *bindex1;
  3275.   short int *blockvals;
  3276.   int forw_row_start, back_row_start, forw_col_start, back_col_start;
  3277.  
  3278. #ifdef LOOSE_MPEG
  3279.   int illegal_forw = 0;
  3280.   int illegal_back = 0;
  3281. #endif
  3282.  
  3283.   /* Calculate macroblock row and column from address. */
  3284.  
  3285.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  3286.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  3287.  
  3288.   /* If block is luminance block... */
  3289.  
  3290.   if (bnum < 4) {
  3291.  
  3292.     /*
  3293.      * Calculate right_for, down_for, right_half_for, down_half_for,
  3294.      * right_back, down_bakc, right_half_back, and down_half_back, motion
  3295.      * vectors.
  3296.      */
  3297.  
  3298.     right_for = recon_right_for >> 1;
  3299.     down_for = recon_down_for >> 1;
  3300.     right_half_for = recon_right_for & 0x1;
  3301.     down_half_for = recon_down_for & 0x1;
  3302.  
  3303.     right_back = recon_right_back >> 1;
  3304.     down_back = recon_down_back >> 1;
  3305.     right_half_back = recon_right_back & 0x1;
  3306.     down_half_back = recon_down_back & 0x1;
  3307.  
  3308.     /* Set dest to luminance plane of current pict image. */
  3309.  
  3310.     dest = vid_stream->current->luminance;
  3311.  
  3312.     /* If past frame exists, set past to luminance plane of past frame. */
  3313.  
  3314.     if (vid_stream->past != NULL)
  3315.       past = vid_stream->past->luminance;
  3316.  
  3317.     /*
  3318.      * If future frame exists, set future to luminance plane of future frame.
  3319.      */
  3320.  
  3321.     if (vid_stream->future != NULL)
  3322.       future = vid_stream->future->luminance;
  3323.  
  3324.     /* Establish row size. */
  3325.  
  3326.     row_size = (vid_stream->mb_width << 4);
  3327.  
  3328.     /* Calculate row,col of upper left pixel in block. */
  3329.  
  3330.     row = (mb_row << 4);
  3331.     col = (mb_col << 4);
  3332.     if (bnum > 1)
  3333.       row += 8;
  3334.     if (bnum & 0x01)
  3335.       col += 8;
  3336.  
  3337.     forw_col_start = col + right_for;
  3338.     forw_row_start = row + down_for;
  3339.  
  3340.     back_col_start = col + right_back;
  3341.     back_row_start = row + down_back;
  3342.  
  3343. #ifdef LOOSE_MPEG
  3344.  
  3345.     /* Check for illegal pred. blocks. */
  3346.  
  3347.  
  3348.     if (forw_col_start+7 > lmaxx) illegal_forw = 1;
  3349.     else if (forw_col_start < 0) illegal_forw = 1;
  3350.  
  3351.     if (forw_row_start+7 > lmaxy) illegal_forw = 1;
  3352.     else if (forw_row_start < 0) illegal_forw = 1;
  3353.  
  3354.     if (back_col_start+7 > lmaxx) illegal_back = 1;
  3355.     else if (back_col_start < 0) illegal_back = 1;
  3356.  
  3357.     if (back_row_start+7 > lmaxy) illegal_back = 1;
  3358.     else if (back_row_start < 0) illegal_back = 1;
  3359.  
  3360. #endif
  3361.  
  3362.   }
  3363.   /* Otherwise, block is NOT luminance block, ... */
  3364.  
  3365.   else {
  3366.  
  3367.     /* Construct motion vectors. */
  3368.  
  3369.     recon_right_for /= 2;
  3370.     recon_down_for /= 2;
  3371.     right_for = recon_right_for >> 1;
  3372.     down_for = recon_down_for >> 1;
  3373.     right_half_for = recon_right_for & 0x1;
  3374.     down_half_for = recon_down_for & 0x1;
  3375.  
  3376.     recon_right_back /= 2;
  3377.     recon_down_back /= 2;
  3378.     right_back = recon_right_back >> 1;
  3379.     down_back = recon_down_back >> 1;
  3380.     right_half_back = recon_right_back & 0x1;
  3381.     down_half_back = recon_down_back & 0x1;
  3382.  
  3383.     /* Establish row size. */
  3384.  
  3385.     row_size = (vid_stream->mb_width << 3);
  3386.  
  3387.     /* Calculate row,col of upper left pixel in block. */
  3388.  
  3389.     row = (mb_row << 3);
  3390.     col = (mb_col << 3);
  3391.  
  3392.     forw_col_start = col + right_for;
  3393.     forw_row_start = row + down_for;
  3394.  
  3395.     back_col_start = col + right_back;
  3396.     back_row_start = row + down_back;
  3397.  
  3398. #ifdef LOOSE_MPEG
  3399.  
  3400.     /* Check for illegal pred. blocks. */
  3401.  
  3402.     if (forw_col_start+7 > cmaxx) illegal_forw = 1;
  3403.     else if (forw_col_start < 0) illegal_forw = 1;
  3404.  
  3405.     if (forw_row_start+7 > cmaxy) illegal_forw = 1;
  3406.     else if (forw_row_start < 0) illegal_forw = 1;
  3407.  
  3408.     if (back_col_start+7 > cmaxx) illegal_back = 1;
  3409.     else if (back_col_start < 0) illegal_back = 1;
  3410.     
  3411.     if (back_row_start+7 > cmaxy) illegal_back = 1;
  3412.     else if (back_row_start < 0) illegal_back = 1;
  3413.  
  3414. #endif
  3415.     
  3416.     /* If block is Cr block... */
  3417.     /* Switched earlier, so we test Cr first - eyhung */
  3418.  
  3419.     if (bnum == 5) {
  3420.  
  3421.       /* Set dest to Cr plane of current pict image. */
  3422.  
  3423.       dest = vid_stream->current->Cr;
  3424.  
  3425.       /* If past frame exists, set past to Cr plane of past image. */
  3426.  
  3427.       if (vid_stream->past != NULL)
  3428.     past = vid_stream->past->Cr;
  3429.  
  3430.       /*
  3431.        * If future frame exists, set future to Cr plane of future image.
  3432.        */
  3433.  
  3434.       if (vid_stream->future != NULL)
  3435.     future = vid_stream->future->Cr;
  3436.     }
  3437.     /* Otherwise, block is Cb block... */
  3438.  
  3439.     else {
  3440.  
  3441.       /* Set dest to Cb plane of current pict image. */
  3442.  
  3443.       dest = vid_stream->current->Cb;
  3444.  
  3445.       /* If past frame exists, set past to Cb plane of past frame. */
  3446.  
  3447.       if (vid_stream->past != NULL)
  3448.     past = vid_stream->past->Cb;
  3449.  
  3450.       /*
  3451.        * If future frame exists, set future to Cb plane of future frame.
  3452.        */
  3453.  
  3454.       if (vid_stream->future != NULL)
  3455.     future = vid_stream->future->Cb;
  3456.     }
  3457.   }
  3458.  
  3459.   /* For each pixel in block... */
  3460.  
  3461.   index = dest + (row * row_size) + col;
  3462.  
  3463. #ifdef LOOSE_MPEG
  3464.   if (illegal_forw) 
  3465.     rindex1 = future + back_row_start * row_size + back_col_start;
  3466.   else 
  3467. #endif
  3468.     rindex1 = past + forw_row_start  * row_size + forw_col_start;
  3469.  
  3470. #ifdef LOOSE_MPEG
  3471.   if (illegal_back) 
  3472.     bindex1 = past + forw_row_start * row_size + forw_col_start;
  3473.   else 
  3474. #endif
  3475.     bindex1 = future + back_row_start * row_size + back_col_start;
  3476.  
  3477.   blockvals = (short int *) &(vid_stream->block.dct_recon[0][0]);
  3478.  
  3479.   {
  3480.   unsigned char *cm = cropTbl + MAX_NEG_CROP;
  3481.   if (!zflag)
  3482.     for (rr = 0; rr < 4; rr++) {
  3483.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[0]];
  3484.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[1]];
  3485.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[2]];
  3486.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[3]];
  3487.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[4]];
  3488.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[5]];
  3489.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[6]];
  3490.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[7]];
  3491.       index += row_size;
  3492.       rindex1 += row_size;
  3493.       bindex1 += row_size;
  3494.  
  3495.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[8]];
  3496.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[9]];
  3497.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[10]];
  3498.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[11]];
  3499.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[12]];
  3500.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[13]];
  3501.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[14]];
  3502.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[15]];
  3503.       blockvals += 16;
  3504.       index += row_size;
  3505.       rindex1 += row_size;
  3506.       bindex1 += row_size;
  3507.     }
  3508.  
  3509.   else
  3510.     for (rr = 0; rr < 4; rr++) {
  3511.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  3512.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  3513.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  3514.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  3515.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  3516.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  3517.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  3518.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  3519.       index += row_size;
  3520.       rindex1 += row_size;
  3521.       bindex1 += row_size;
  3522.  
  3523.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  3524.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  3525.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  3526.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  3527.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  3528.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  3529.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  3530.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  3531.       index += row_size;
  3532.       rindex1 += row_size;
  3533.       bindex1 += row_size;
  3534.     }
  3535.   }
  3536. }
  3537.  
  3538.  
  3539. /*
  3540.  *--------------------------------------------------------------
  3541.  *
  3542.  * ProcessSkippedPFrameMBlocks --
  3543.  *
  3544.  *    Processes skipped macroblocks in P frames.
  3545.  *
  3546.  * Results:
  3547.  *    Calculates pixel values for luminance, Cr, and Cb planes
  3548.  *      in current pict image for skipped macroblocks.
  3549.  *
  3550.  * Side effects:
  3551.  *    Pixel values in pict image changed.
  3552.  *
  3553.  *--------------------------------------------------------------
  3554.  */
  3555.  
  3556. static void
  3557. ProcessSkippedPFrameMBlocks(vid_stream)
  3558.   VidStream *vid_stream;
  3559. {
  3560.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  3561.   int addr, row_incr, half_row_incr, crow, ccol;
  3562.   int *dest, *src, *dest1, *src1;
  3563.  
  3564.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  3565.  
  3566.   row_size = vid_stream->mb_width << 4;
  3567.   half_row = (row_size >> 1);
  3568.   row_incr = row_size >> 2;
  3569.   half_row_incr = half_row >> 2;
  3570.  
  3571.   /* For each skipped macroblock, do... */
  3572.  
  3573.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  3574.        addr < vid_stream->mblock.mb_address; addr++) {
  3575.  
  3576.     /* Calculate macroblock row and col. */
  3577.  
  3578.     mb_row = addr / vid_stream->mb_width;
  3579.     mb_col = addr % vid_stream->mb_width;
  3580.  
  3581.     /* Calculate upper left pixel row,col for luminance plane. */
  3582.  
  3583.     row = mb_row << 4;
  3584.     col = mb_col << 4;
  3585.  
  3586.  
  3587.     /* For each row in macroblock luminance plane... */
  3588.  
  3589.     dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3590.     src = (int *)(vid_stream->future->luminance + (row * row_size) + col);
  3591.  
  3592.     for (rr = 0; rr < 8; rr++) {
  3593.  
  3594.       /* Copy pixel values from last I or P picture. */
  3595.  
  3596.       dest[0] = src[0];
  3597.       dest[1] = src[1];
  3598.       dest[2] = src[2];
  3599.       dest[3] = src[3];
  3600.       dest += row_incr;
  3601.       src += row_incr;
  3602.  
  3603.       dest[0] = src[0];
  3604.       dest[1] = src[1];
  3605.       dest[2] = src[2];
  3606.       dest[3] = src[3];
  3607.       dest += row_incr;
  3608.       src += row_incr;
  3609.     }
  3610.  
  3611.     /*
  3612.      * Divide row,col to get upper left pixel of macroblock in Cr and Cb
  3613.      * planes.
  3614.      */
  3615.  
  3616.     crow = row >> 1;
  3617.     ccol = col >> 1;
  3618.  
  3619.     /* For each row in Cr, and Cb planes... */
  3620.  
  3621.     dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3622.     src = (int *)(vid_stream->future->Cr + (crow * half_row) + ccol);
  3623.     dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3624.     src1 = (int *)(vid_stream->future->Cb + (crow * half_row) + ccol);
  3625.  
  3626.     for (rr = 0; rr < 4; rr++) {
  3627.  
  3628.       /* Copy pixel values from last I or P picture. */
  3629.  
  3630.       dest[0] = src[0];
  3631.       dest[1] = src[1];
  3632.  
  3633.       dest1[0] = src1[0];
  3634.       dest1[1] = src1[1];
  3635.  
  3636.       dest += half_row_incr;
  3637.       src += half_row_incr;
  3638.       dest1 += half_row_incr;
  3639.       src1 += half_row_incr;
  3640.  
  3641.       dest[0] = src[0];
  3642.       dest[1] = src[1];
  3643.  
  3644.       dest1[0] = src1[0];
  3645.       dest1[1] = src1[1];
  3646.  
  3647.       dest += half_row_incr;
  3648.       src += half_row_incr;
  3649.       dest1 += half_row_incr;
  3650.       src1 += half_row_incr;
  3651.     }
  3652.  
  3653.     if (ditherType == MBORDERED_DITHER) {
  3654.       MBOrderedDitherDisplayCopy(vid_stream, addr,
  3655.                  1, 0, 0, 0, 0, 0,
  3656.                  vid_stream->future->display,
  3657.                  (unsigned char *) NULL);
  3658.       ditherFlags[addr] = 0;
  3659.     }
  3660.   }
  3661.  
  3662.   vid_stream->mblock.recon_right_for_prev = 0;
  3663.   vid_stream->mblock.recon_down_for_prev = 0;
  3664. }
  3665.  
  3666.  
  3667.  
  3668.  
  3669.  
  3670. /*
  3671.  *--------------------------------------------------------------
  3672.  *
  3673.  * ProcessSkippedBFrameMBlocks --
  3674.  *
  3675.  *    Processes skipped macroblocks in B frames.
  3676.  *
  3677.  * Results:
  3678.  *    Calculates pixel values for luminance, Cr, and Cb planes
  3679.  *      in current pict image for skipped macroblocks.
  3680.  *
  3681.  * Side effects:
  3682.  *    Pixel values in pict image changed.
  3683.  *
  3684.  *--------------------------------------------------------------
  3685.  */
  3686.  
  3687. static void
  3688. ProcessSkippedBFrameMBlocks(vid_stream)
  3689.   VidStream *vid_stream;
  3690. {
  3691.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  3692.   int right_half_for = 0, down_half_for = 0;
  3693.   int c_right_half_for = 0, c_down_half_for = 0;
  3694.   int right_half_back = 0, down_half_back = 0;
  3695.   int c_right_half_back = 0, c_down_half_back = 0;
  3696.   int addr, right_for = 0, down_for = 0;
  3697.   int recon_right_for, recon_down_for;
  3698.   int recon_right_back, recon_down_back;
  3699.   int right_back = 0, down_back = 0;
  3700.   int c_right_for = 0, c_down_for = 0;
  3701.   int c_right_back = 0, c_down_back = 0;
  3702.   unsigned char forw_lum[256];
  3703.   unsigned char forw_cr[64], forw_cb[64];
  3704.   unsigned char back_lum[256], back_cr[64], back_cb[64];
  3705.   int row_incr, half_row_incr;
  3706.   int ccol, crow;
  3707.  
  3708.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  3709.  
  3710.   row_size = vid_stream->mb_width << 4;
  3711.   half_row = (row_size >> 1);
  3712.   row_incr = row_size >> 2;
  3713.   half_row_incr =  half_row >> 2;
  3714.  
  3715.   /* Establish motion vector codes based on full pixel flag. */
  3716.  
  3717.   if (vid_stream->picture.full_pel_forw_vector) {
  3718.     recon_right_for = vid_stream->mblock.recon_right_for_prev << 1;
  3719.     recon_down_for = vid_stream->mblock.recon_down_for_prev << 1;
  3720.   } else {
  3721.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  3722.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  3723.   }
  3724.  
  3725.   if (vid_stream->picture.full_pel_back_vector) {
  3726.     recon_right_back = vid_stream->mblock.recon_right_back_prev << 1;
  3727.     recon_down_back = vid_stream->mblock.recon_down_back_prev << 1;
  3728.   } else {
  3729.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  3730.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  3731.   }
  3732.  
  3733.  
  3734.   /* If only one motion vector, do display copy, else do full
  3735.      calculation. 
  3736.   */
  3737.  
  3738.   if (ditherType == MBORDERED_DITHER) {
  3739.     if (vid_stream->mblock.bpict_past_forw &&
  3740.     !vid_stream->mblock.bpict_past_back) {
  3741.       for (addr = vid_stream->mblock.past_mb_addr+1;
  3742.        addr < vid_stream->mblock.mb_address; addr++) {
  3743.     
  3744.     MBOrderedDitherDisplayCopy(vid_stream, addr,
  3745.                    1, recon_right_for, recon_down_for,
  3746.                  0, 0, 0, vid_stream->past->display,
  3747.                    vid_stream->future->display);
  3748.     ditherFlags[addr] = 0;
  3749.       }
  3750.       return;
  3751.     }
  3752.     if (vid_stream->mblock.bpict_past_back && 
  3753.     !vid_stream->mblock.bpict_past_forw) {
  3754.       for (addr = vid_stream->mblock.past_mb_addr+1;
  3755.        addr < vid_stream->mblock.mb_address; addr++) {
  3756.     
  3757.     MBOrderedDitherDisplayCopy(vid_stream, addr,
  3758.                    0, 0, 0,
  3759.                    1, recon_right_back, recon_down_back,
  3760.                    vid_stream->past->display, vid_stream->future->display);
  3761.     ditherFlags[addr] = 0;
  3762.       }
  3763.       return;
  3764.     }
  3765.   }
  3766.  
  3767.   /* Calculate motion vectors. */
  3768.   
  3769.   if (vid_stream->mblock.bpict_past_forw) {
  3770.     right_for = recon_right_for >> 1;
  3771.     down_for = recon_down_for >> 1;
  3772.     right_half_for = recon_right_for & 0x1;
  3773.     down_half_for = recon_down_for & 0x1;
  3774.     
  3775.     recon_right_for /= 2;
  3776.     recon_down_for /= 2;
  3777.     c_right_for = recon_right_for >> 1;
  3778.     c_down_for = recon_down_for >> 1;
  3779.     c_right_half_for = recon_right_for & 0x1;
  3780.     c_down_half_for = recon_down_for & 0x1;
  3781.     
  3782.   }
  3783.   if (vid_stream->mblock.bpict_past_back) {
  3784.     right_back = recon_right_back >> 1;
  3785.     down_back = recon_down_back >> 1;
  3786.     right_half_back = recon_right_back & 0x1;
  3787.     down_half_back = recon_down_back & 0x1;
  3788.     
  3789.     recon_right_back /= 2;
  3790.     recon_down_back /= 2;
  3791.     c_right_back = recon_right_back >> 1;
  3792.     c_down_back = recon_down_back >> 1;
  3793.     c_right_half_back = recon_right_back & 0x1;
  3794.     c_down_half_back = recon_down_back & 0x1;
  3795.     
  3796.   }
  3797.   /* For each skipped macroblock, do... */
  3798.   
  3799.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  3800.        addr < vid_stream->mblock.mb_address; addr++) {
  3801.     
  3802.     /* Calculate macroblock row and col. */
  3803.     
  3804.     mb_row = addr / vid_stream->mb_width;
  3805.     mb_col = addr % vid_stream->mb_width;
  3806.     
  3807.     /* Calculate upper left pixel row,col for luminance plane. */
  3808.     
  3809.     row = mb_row << 4;
  3810.     col = mb_col << 4;
  3811.     crow = row / 2;
  3812.     ccol = col / 2;
  3813.     
  3814.     /* If forward predicted, calculate prediction values. */
  3815.     
  3816.     if (vid_stream->mblock.bpict_past_forw) {
  3817.       
  3818.       ReconSkippedBlock(vid_stream->past->luminance, forw_lum,
  3819.             row, col, row_size, right_for, down_for,
  3820.             right_half_for, down_half_for, 16);
  3821.       ReconSkippedBlock(vid_stream->past->Cr, forw_cr, crow,
  3822.             ccol, half_row,
  3823.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  3824.       ReconSkippedBlock(vid_stream->past->Cb, forw_cb, crow,
  3825.             ccol, half_row,
  3826.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  3827.     }
  3828.     /* If back predicted, calculate prediction values. */
  3829.     
  3830.     if (vid_stream->mblock.bpict_past_back) {
  3831.       ReconSkippedBlock(vid_stream->future->luminance, back_lum,
  3832.             row, col, row_size, right_back, down_back,
  3833.             right_half_back, down_half_back, 16);
  3834.       ReconSkippedBlock(vid_stream->future->Cr, back_cr, crow,
  3835.             ccol, half_row,
  3836.             c_right_back, c_down_back,
  3837.             c_right_half_back, c_down_half_back, 8);
  3838.       ReconSkippedBlock(vid_stream->future->Cb, back_cb, crow,
  3839.             ccol, half_row,
  3840.             c_right_back, c_down_back,
  3841.             c_right_half_back, c_down_half_back, 8);
  3842.     }
  3843.     if (vid_stream->mblock.bpict_past_forw &&
  3844.     !vid_stream->mblock.bpict_past_back) {
  3845.       
  3846.       int *dest, *dest1;
  3847.       int *src, *src1;
  3848.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3849.       src = (int *)forw_lum;
  3850.       
  3851.       for (rr = 0; rr < 16; rr++) {
  3852.     
  3853.     /* memcpy(dest, forw_lum+(rr<<4), 16);  */
  3854.     dest[0] = src[0];
  3855.     dest[1] = src[1];
  3856.     dest[2] = src[2];
  3857.     dest[3] = src[3];
  3858.     dest += row_incr;
  3859.     src += 4;
  3860.       }
  3861.       
  3862.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3863.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3864.       src = (int *)forw_cr;
  3865.       src1 = (int *)forw_cb;
  3866.       
  3867.       for (rr = 0; rr < 8; rr++) {
  3868.     /*
  3869.      * memcpy(dest, forw_cr+(rr<<3), 8); memcpy(dest1, forw_cb+(rr<<3),
  3870.      * 8);
  3871.      */
  3872.     
  3873.     dest[0] = src[0];
  3874.     dest[1] = src[1];
  3875.     
  3876.     dest1[0] = src1[0];
  3877.     dest1[1] = src1[1];
  3878.     
  3879.     dest += half_row_incr;
  3880.     dest1 += half_row_incr;
  3881.     src += 2;
  3882.     src1 += 2;
  3883.       }
  3884.     } else if (vid_stream->mblock.bpict_past_back &&
  3885.            !vid_stream->mblock.bpict_past_forw) {
  3886.       
  3887.       int *src, *src1;
  3888.       int *dest, *dest1;
  3889.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3890.       src = (int *)back_lum;
  3891.       
  3892.       for (rr = 0; rr < 16; rr++) {
  3893.     dest[0] = src[0];
  3894.     dest[1] = src[1];
  3895.     dest[2] = src[2];
  3896.     dest[3] = src[3];
  3897.     dest += row_incr;
  3898.     src += 4;
  3899.       }
  3900.       
  3901.       
  3902.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3903.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3904.       src = (int *)back_cr;
  3905.       src1 = (int *)back_cb;
  3906.       
  3907.       for (rr = 0; rr < 8; rr++) {
  3908.     /*
  3909.      * memcpy(dest, back_cr+(rr<<3), 8); memcpy(dest1, back_cb+(rr<<3),
  3910.      * 8);
  3911.      */
  3912.     
  3913.     dest[0] = src[0];
  3914.     dest[1] = src[1];
  3915.     
  3916.     dest1[0] = src1[0];
  3917.     dest1[1] = src1[1];
  3918.     
  3919.     dest += half_row_incr;
  3920.     dest1 += half_row_incr;
  3921.     src += 2;
  3922.     src1 += 2;
  3923.       }
  3924.     } else {
  3925.       
  3926.       unsigned char *src1, *src2, *src1a, *src2a;
  3927.       unsigned char *dest, *dest1;
  3928.       dest = vid_stream->current->luminance + (row * row_size) + col;
  3929.       src1 = forw_lum;
  3930.       src2 = back_lum;
  3931.       
  3932.       for (rr = 0; rr < 16; rr++) {
  3933.         dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3934.         dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3935.         dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3936.         dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3937.         dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3938.         dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3939.         dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3940.         dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3941.         dest[8] = (int) (src1[8] + src2[8]) >> 1;
  3942.         dest[9] = (int) (src1[9] + src2[9]) >> 1;
  3943.         dest[10] = (int) (src1[10] + src2[10]) >> 1;
  3944.         dest[11] = (int) (src1[11] + src2[11]) >> 1;
  3945.         dest[12] = (int) (src1[12] + src2[12]) >> 1;
  3946.         dest[13] = (int) (src1[13] + src2[13]) >> 1;
  3947.         dest[14] = (int) (src1[14] + src2[14]) >> 1;
  3948.         dest[15] = (int) (src1[15] + src2[15]) >> 1;
  3949.         dest += row_size;
  3950.         src1 += 16;
  3951.         src2 += 16;
  3952.       }
  3953.       
  3954.       
  3955.       dest = vid_stream->current->Cr + (crow * half_row) + ccol;
  3956.       dest1 = vid_stream->current->Cb + (crow * half_row) + ccol;
  3957.       src1 = forw_cr;
  3958.       src2 = back_cr;
  3959.       src1a = forw_cb;
  3960.       src2a = back_cb;
  3961.       
  3962.       for (rr = 0; rr < 8; rr++) {
  3963.         dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3964.         dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3965.         dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3966.         dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3967.         dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3968.         dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3969.         dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3970.         dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3971.         dest += half_row;
  3972.         src1 += 8;
  3973.         src2 += 8;
  3974.     
  3975.         dest1[0] = (int) (src1a[0] + src2a[0]) >> 1;
  3976.         dest1[1] = (int) (src1a[1] + src2a[1]) >> 1;
  3977.         dest1[2] = (int) (src1a[2] + src2a[2]) >> 1;
  3978.         dest1[3] = (int) (src1a[3] + src2a[3]) >> 1;
  3979.         dest1[4] = (int) (src1a[4] + src2a[4]) >> 1;
  3980.         dest1[5] = (int) (src1a[5] + src2a[5]) >> 1;
  3981.         dest1[6] = (int) (src1a[6] + src2a[6]) >> 1;
  3982.         dest1[7] = (int) (src1a[7] + src2a[7]) >> 1;
  3983.         dest1 += half_row;
  3984.         src1a += 8;
  3985.         src2a += 8;
  3986.       }
  3987.     }
  3988.     
  3989.     if (ditherType == MBORDERED_DITHER) {
  3990.       ditherFlags[addr] = 1;
  3991.     }
  3992.   }
  3993. }
  3994.  
  3995.  
  3996.  
  3997.  
  3998.  
  3999. /*
  4000.  *--------------------------------------------------------------
  4001.  *
  4002.  * ReconSkippedBlock --
  4003.  *
  4004.  *    Reconstructs predictive block for skipped macroblocks
  4005.  *      in B Frames.
  4006.  *
  4007.  * Results:
  4008.  *    No return values.
  4009.  *
  4010.  * Side effects:
  4011.  *    None.
  4012.  *
  4013.  *--------------------------------------------------------------
  4014.  */
  4015.  
  4016. static void
  4017. ReconSkippedBlock(source, dest, row, col, row_size,
  4018.           right, down, right_half, down_half, width)
  4019.   unsigned char *source;
  4020.   unsigned char *dest;
  4021.   int row, col, row_size, right, down, right_half, down_half, width;
  4022. {
  4023.   int rr;
  4024.   unsigned char *source2;
  4025.  
  4026.   source += ((row + down) * row_size) + col + right;
  4027.  
  4028.   if (width == 16) {
  4029.     if ((!right_half) && (!down_half)) {
  4030.     if (right & 0x1) {
  4031.       /* No alignment, use bye copy */
  4032.       for (rr = 0; rr < 16; rr++) {
  4033.         dest[0] = source[0];
  4034.         dest[1] = source[1];
  4035.         dest[2] = source[2];
  4036.         dest[3] = source[3];
  4037.         dest[4] = source[4];
  4038.         dest[5] = source[5];
  4039.         dest[6] = source[6];
  4040.         dest[7] = source[7];
  4041.         dest[8] = source[8];
  4042.         dest[9] = source[9];
  4043.         dest[10] = source[10];
  4044.         dest[11] = source[11];
  4045.         dest[12] = source[12];
  4046.         dest[13] = source[13];
  4047.         dest[14] = source[14];
  4048.         dest[15] = source[15];
  4049.         dest += 16;
  4050.         source += row_size;
  4051.       }
  4052.     } else if (right & 0x2) {
  4053.       /* Half-word bit aligned, use 16 bit copy */
  4054.       short *src = (short *)source;
  4055.       short *d = (short *)dest;
  4056.       row_size >>= 1;
  4057.       for (rr = 0; rr < 16; rr++) {
  4058.         d[0] = src[0];
  4059.         d[1] = src[1];
  4060.         d[2] = src[2];
  4061.         d[3] = src[3];
  4062.         d[4] = src[4];
  4063.         d[5] = src[5];
  4064.         d[6] = src[6];
  4065.         d[7] = src[7];
  4066.         d += 8;
  4067.         src += row_size;
  4068.       }
  4069.     } else {
  4070.       /* Word aligned, use 32 bit copy */
  4071.       int *src = (int *)source;
  4072.       int *d = (int *)dest;
  4073.       row_size >>= 2;
  4074.       for (rr = 0; rr < 16; rr++) {
  4075.         d[0] = src[0];
  4076.         d[1] = src[1];
  4077.         d[2] = src[2];
  4078.         d[3] = src[3];
  4079.         d += 4;
  4080.         src += row_size;
  4081.       }
  4082.     }
  4083.     } else {
  4084.       source2 = source + right_half + (row_size * down_half);
  4085.       for (rr = 0; rr < width; rr++) {
  4086.         dest[0] = (int) (source[0] + source2[0]) >> 1;
  4087.         dest[1] = (int) (source[1] + source2[1]) >> 1;
  4088.         dest[2] = (int) (source[2] + source2[2]) >> 1;
  4089.         dest[3] = (int) (source[3] + source2[3]) >> 1;
  4090.         dest[4] = (int) (source[4] + source2[4]) >> 1;
  4091.         dest[5] = (int) (source[5] + source2[5]) >> 1;
  4092.         dest[6] = (int) (source[6] + source2[6]) >> 1;
  4093.         dest[7] = (int) (source[7] + source2[7]) >> 1;
  4094.         dest[8] = (int) (source[8] + source2[8]) >> 1;
  4095.         dest[9] = (int) (source[9] + source2[9]) >> 1;
  4096.         dest[10] = (int) (source[10] + source2[10]) >> 1;
  4097.         dest[11] = (int) (source[11] + source2[11]) >> 1;
  4098.         dest[12] = (int) (source[12] + source2[12]) >> 1;
  4099.         dest[13] = (int) (source[13] + source2[13]) >> 1;
  4100.         dest[14] = (int) (source[14] + source2[14]) >> 1;
  4101.         dest[15] = (int) (source[15] + source2[15]) >> 1;
  4102.         dest += width;
  4103.         source += row_size;
  4104.         source2 += row_size;
  4105.       }
  4106.     }
  4107.   } else {            /* (width == 8) */
  4108.     assert(width == 8);
  4109.     if ((!right_half) && (!down_half)) {
  4110.       if (right & 0x1) {
  4111.     for (rr = 0; rr < width; rr++) {
  4112.       dest[0] = source[0];
  4113.       dest[1] = source[1];
  4114.       dest[2] = source[2];
  4115.       dest[3] = source[3];
  4116.       dest[4] = source[4];
  4117.       dest[5] = source[5];
  4118.       dest[6] = source[6];
  4119.       dest[7] = source[7];
  4120.       dest += 8;
  4121.       source += row_size;
  4122.     }
  4123.       } else if (right & 0x02) {
  4124.     short *d = (short *)dest;
  4125.     short *src = (short *)source;
  4126.     row_size >>= 1;
  4127.     for (rr = 0; rr < width; rr++) {
  4128.       d[0] = src[0];
  4129.       d[1] = src[1];
  4130.       d[2] = src[2];
  4131.       d[3] = src[3];
  4132.       d += 4;
  4133.       src += row_size;
  4134.     }
  4135.       } else {
  4136.     int *d = (int *)dest;
  4137.     int *src = (int *)source;
  4138.     row_size >>= 2;
  4139.     for (rr = 0; rr < width; rr++) {
  4140.       d[0] = src[0];
  4141.       d[1] = src[1];
  4142.       d += 2;
  4143.       src += row_size;
  4144.     }
  4145.       }
  4146.     } else {
  4147.       source2 = source + right_half + (row_size * down_half);
  4148.       for (rr = 0; rr < width; rr++) {
  4149.         dest[0] = (int) (source[0] + source2[0]) >> 1;
  4150.         dest[1] = (int) (source[1] + source2[1]) >> 1;
  4151.         dest[2] = (int) (source[2] + source2[2]) >> 1;
  4152.         dest[3] = (int) (source[3] + source2[3]) >> 1;
  4153.         dest[4] = (int) (source[4] + source2[4]) >> 1;
  4154.         dest[5] = (int) (source[5] + source2[5]) >> 1;
  4155.         dest[6] = (int) (source[6] + source2[6]) >> 1;
  4156.         dest[7] = (int) (source[7] + source2[7]) >> 1;
  4157.         dest += width;
  4158.         source += row_size;
  4159.         source2 += row_size;
  4160.       }
  4161.     }
  4162.   }
  4163. }
  4164.  
  4165.  
  4166.  
  4167.  
  4168. /*
  4169.  *--------------------------------------------------------------
  4170.  *
  4171.  * DoPictureDisplay --
  4172.  *
  4173.  *    Converts image from Lum, Cr, Cb to colormap space. Puts
  4174.  *      image in lum plane. Updates past and future frame
  4175.  *      pointers. Dithers image. Sends to display mechanism.
  4176.  *
  4177.  * Results:
  4178.  *    Pict image structure locked if displaying or if frame
  4179.  *      is needed as past or future reference.
  4180.  *
  4181.  * Side effects:
  4182.  *    Lum plane pummelled.
  4183.  *
  4184.  *--------------------------------------------------------------
  4185.  */
  4186.  
  4187. static void
  4188. DoPictureDisplay(vid_stream)
  4189.   VidStream *vid_stream;
  4190. {
  4191.  
  4192.   /* Convert to colormap space and dither. */
  4193.  
  4194.   DoDitherImage(vid_stream->current->luminance, 
  4195.         vid_stream->current->Cr,
  4196.         vid_stream->current->Cb, vid_stream->current->display,
  4197.         (int) vid_stream->mb_height * 16, (int) vid_stream->mb_width * 16);
  4198.  
  4199.   /* Update past and future references if needed. */
  4200.  
  4201.   if ((vid_stream->picture.code_type == I_TYPE) || (vid_stream->picture.code_type == P_TYPE)) {
  4202.     if (vid_stream->future == NULL) {
  4203.       vid_stream->future = vid_stream->current;
  4204.       vid_stream->future->locked |= FUTURE_LOCK;
  4205.     } else {
  4206.       if (vid_stream->past != NULL) {
  4207.     vid_stream->past->locked &= ~PAST_LOCK;
  4208.       }
  4209.       vid_stream->past = vid_stream->future;
  4210.       vid_stream->past->locked &= ~FUTURE_LOCK;
  4211.       vid_stream->past->locked |= PAST_LOCK;
  4212.       vid_stream->future = vid_stream->current;
  4213.       vid_stream->future->locked |= FUTURE_LOCK;
  4214.       vid_stream->current = vid_stream->past;
  4215.       ExecuteDisplay(vid_stream);
  4216.     }
  4217.   } else
  4218.     ExecuteDisplay(vid_stream);
  4219.  
  4220. }
  4221.  
  4222.  
  4223.  
  4224.  
  4225. /*
  4226.  *--------------------------------------------------------------
  4227.  *
  4228.  * SetBFlag --
  4229.  *
  4230.  *    Called to set no b frame processing flag.
  4231.  *
  4232.  * Results:
  4233.  *      No_B_Flag flag is set to its argument.
  4234.  *
  4235.  * Side effects:
  4236.  *      None.
  4237.  *
  4238.  *--------------------------------------------------------------
  4239.  */
  4240.  
  4241. void
  4242. SetBFlag(val)
  4243. BOOLEAN val;
  4244. {
  4245.     No_B_Flag = val;
  4246. }
  4247.  
  4248.  
  4249.  
  4250.  
  4251.  
  4252. /*
  4253.  *--------------------------------------------------------------
  4254.  *
  4255.  * SetPFlag --
  4256.  *
  4257.  *    Called to set no p frame processing flag.
  4258.  *
  4259.  * Results:
  4260.  *      No_P_Flag flag is set to value of argument
  4261.  *
  4262.  * Side effects:
  4263.  *      None.
  4264.  *
  4265.  *--------------------------------------------------------------
  4266.  */
  4267.  
  4268. void
  4269. SetPFlag(val)
  4270. BOOLEAN val;
  4271. {
  4272.     No_P_Flag = val;
  4273. }
  4274.